--- a/services/common/remote-settings.js
+++ b/services/common/remote-settings.js
@@ -19,17 +19,18 @@ ChromeUtils.defineModuleGetter(this, "Ki
ChromeUtils.defineModuleGetter(this, "KintoHttpClient",
"resource://services-common/kinto-http-client.js");
ChromeUtils.defineModuleGetter(this, "CanonicalJSON",
"resource://gre/modules/CanonicalJSON.jsm");
ChromeUtils.defineModuleGetter(this, "UptakeTelemetry",
"resource://services-common/uptake-telemetry.js");
ChromeUtils.defineModuleGetter(this, "ClientEnvironmentBase",
"resource://gre/modules/components-utils/ClientEnvironment.jsm");
-ChromeUtils.defineModuleGetter(this, "FilterExpressions", "resource://normandy/lib/FilterExpressions.jsm");
+ChromeUtils.defineModuleGetter(this, "FilterExpressions",
+ "resource://gre/modules/components-utils/FilterExpressions.jsm");
const PREF_SETTINGS_SERVER = "services.settings.server";
const PREF_SETTINGS_DEFAULT_BUCKET = "services.settings.default_bucket";
const PREF_SETTINGS_DEFAULT_SIGNER = "services.settings.default_signer";
const PREF_SETTINGS_VERIFY_SIGNATURE = "services.settings.verify_signature";
const PREF_SETTINGS_SERVER_BACKOFF = "services.settings.server.backoff";
const PREF_SETTINGS_CHANGES_PATH = "services.settings.changes.path";
const PREF_SETTINGS_LAST_UPDATE = "services.settings.last_update_seconds";
--- a/services/common/tests/unit/test_blocklist_clients.js
+++ b/services/common/tests/unit/test_blocklist_clients.js
@@ -241,22 +241,16 @@ add_task(async function test_sync_event_
const collection = await client.openCollection();
const { data: internalData } = await collection.list();
ok(internalData.length > current.length, `event current data for ${client.collectionName}`);
}
});
add_task(clear_state);
add_task(async function test_entries_are_filtered_when_jexl_filters_is_present() {
- if (IS_ANDROID) {
- // JEXL filters are not supported on Android.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=1463502
- return;
- }
-
const records = [{
willMatch: true,
}, {
willMatch: true,
filters: null
}, {
willMatch: true,
filters: "1 == 1"
--- a/services/common/tests/unit/xpcshell.ini
+++ b/services/common/tests/unit/xpcshell.ini
@@ -18,17 +18,16 @@ tags = blocklist
tags = blocklist
[test_blocklist_pinning.js]
tags = blocklist
[test_remote_settings.js]
tags = remote-settings blocklist
[test_remote_settings_poll.js]
tags = remote-settings blocklist
[test_remote_settings_jexl_filters.js]
-skip-if = os == "android"
tags = remote-settings
[test_kinto.js]
tags = blocklist
[test_blocklist_signatures.js]
tags = remote-settings blocklist
[test_storage_adapter.js]
tags = remote-settingsblocklist
--- a/toolkit/components/normandy/lib/NormandyDriver.jsm
+++ b/toolkit/components/normandy/lib/NormandyDriver.jsm
@@ -9,21 +9,21 @@ ChromeUtils.import("resource://gre/modul
ChromeUtils.import("resource://gre/modules/Preferences.jsm");
ChromeUtils.import("resource:///modules/ShellService.jsm");
ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
ChromeUtils.import("resource://gre/modules/Timer.jsm");
ChromeUtils.import("resource://normandy/lib/Addons.jsm");
ChromeUtils.import("resource://normandy/lib/LogManager.jsm");
ChromeUtils.import("resource://normandy/lib/Storage.jsm");
ChromeUtils.import("resource://normandy/lib/Heartbeat.jsm");
-ChromeUtils.import("resource://normandy/lib/FilterExpressions.jsm");
ChromeUtils.import("resource://normandy/lib/ClientEnvironment.jsm");
ChromeUtils.import("resource://normandy/lib/PreferenceExperiments.jsm");
-ChromeUtils.import("resource://normandy/lib/Sampling.jsm");
+ChromeUtils.defineModuleGetter(
+ this, "Sampling", "resource://gre/modules/components-utils/Sampling.jsm");
ChromeUtils.defineModuleGetter(this, "UpdateUtils", "resource://gre/modules/UpdateUtils.jsm");
ChromeUtils.defineModuleGetter(
this, "AddonStudies", "resource://normandy/lib/AddonStudies.jsm");
const {generateUUID} = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
var EXPORTED_SYMBOLS = ["NormandyDriver"];
--- a/toolkit/components/normandy/lib/RecipeRunner.jsm
+++ b/toolkit/components/normandy/lib/RecipeRunner.jsm
@@ -9,17 +9,17 @@ ChromeUtils.import("resource://gre/modul
ChromeUtils.import("resource://normandy/lib/LogManager.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "timerManager",
"@mozilla.org/updates/timer-manager;1",
"nsIUpdateTimerManager");
XPCOMUtils.defineLazyModuleGetters(this, {
Storage: "resource://normandy/lib/Storage.jsm",
- FilterExpressions: "resource://normandy/lib/FilterExpressions.jsm",
+ FilterExpressions: "resource://gre/modules/components-utils/FilterExpressions.jsm",
NormandyApi: "resource://normandy/lib/NormandyApi.jsm",
ClientEnvironment: "resource://normandy/lib/ClientEnvironment.jsm",
CleanupManager: "resource://normandy/lib/CleanupManager.jsm",
AddonStudies: "resource://normandy/lib/AddonStudies.jsm",
Uptake: "resource://normandy/lib/Uptake.jsm",
ActionsManager: "resource://normandy/lib/ActionsManager.jsm",
});
--- a/toolkit/components/normandy/test/browser/browser.ini
+++ b/toolkit/components/normandy/test/browser/browser.ini
@@ -14,17 +14,16 @@ skip-if = true # bug 1442712
[browser_ActionSandboxManager.js]
[browser_ActionsManager.js]
[browser_Addons.js]
[browser_AddonStudies.js]
[browser_BaseAction.js]
[browser_CleanupManager.js]
[browser_ClientEnvironment.js]
[browser_EventEmitter.js]
-[browser_FilterExpressions.js]
[browser_Heartbeat.js]
[browser_LogManager.js]
[browser_Normandy.js]
[browser_NormandyDriver.js]
[browser_PreferenceExperiments.js]
[browser_PreferenceRollouts.js]
[browser_RecipeRunner.js]
[browser_ShieldPreferences.js]
--- a/toolkit/components/normandy/test/unit/xpcshell.ini
+++ b/toolkit/components/normandy/test/unit/xpcshell.ini
@@ -4,10 +4,9 @@ support-files =
mock_api/**
invalid_recipe_signature_api/**
query_server.sjs
echo_server.sjs
utils.js
tags = normandy
[test_NormandyApi.js]
-[test_Sampling.js]
[test_SandboxManager.js]
rename from toolkit/components/normandy/lib/FilterExpressions.jsm
rename to toolkit/components/utils/FilterExpressions.jsm
--- a/toolkit/components/normandy/lib/FilterExpressions.jsm
+++ b/toolkit/components/utils/FilterExpressions.jsm
@@ -1,19 +1,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://normandy/lib/Sampling.jsm");
-ChromeUtils.import("resource://normandy/lib/PreferenceFilters.jsm");
-ChromeUtils.defineModuleGetter(this, "mozjexl", "resource://normandy-vendor/mozjexl.js");
+ChromeUtils.defineModuleGetter(this, "PreferenceFilters", "resource://gre/modules/components-utils/PreferenceFilters.jsm");
+ChromeUtils.defineModuleGetter(this, "Sampling", "resource://gre/modules/components-utils/Sampling.jsm");
+ChromeUtils.defineModuleGetter(this, "mozjexl", "resource://gre/modules/components-utils/mozjexl.js");
var EXPORTED_SYMBOLS = ["FilterExpressions"];
XPCOMUtils.defineLazyGetter(this, "jexl", () => {
const jexl = new mozjexl.Jexl();
jexl.addTransforms({
date: dateString => new Date(dateString),
stableSample: Sampling.stableSample,
rename from toolkit/components/normandy/lib/PreferenceFilters.jsm
rename to toolkit/components/utils/PreferenceFilters.jsm
rename from toolkit/components/normandy/lib/Sampling.jsm
rename to toolkit/components/utils/Sampling.jsm
--- a/toolkit/components/utils/moz.build
+++ b/toolkit/components/utils/moz.build
@@ -9,12 +9,17 @@ with Files('**'):
EXTRA_COMPONENTS += [
'simpleServices.js',
'utils.manifest',
]
EXTRA_JS_MODULES['components-utils'] = [
'ClientEnvironment.jsm',
+ 'FilterExpressions.jsm',
'JsonSchemaValidator.jsm',
+ 'mozjexl.js',
+ 'PreferenceFilters.jsm',
+ 'Sampling.jsm',
]
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
+XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
rename from toolkit/components/normandy/vendor/mozjexl.js
rename to toolkit/components/utils/mozjexl.js
new file mode 100644
--- /dev/null
+++ b/toolkit/components/utils/test/unit/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+ "extends": [
+ "plugin:mozilla/xpcshell-test"
+ ]
+};
rename from toolkit/components/normandy/test/browser/browser_FilterExpressions.js
rename to toolkit/components/utils/test/unit/test_FilterExpressions.js
--- a/toolkit/components/normandy/test/browser/browser_FilterExpressions.js
+++ b/toolkit/components/utils/test/unit/test_FilterExpressions.js
@@ -1,39 +1,42 @@
"use strict";
-ChromeUtils.import("resource://normandy/lib/FilterExpressions.jsm", this);
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+ChromeUtils.defineModuleGetter(this, "FilterExpressions",
+ "resource://gre/modules/components-utils/FilterExpressions.jsm");
// Basic JEXL tests
add_task(async function() {
let val;
// Test that basic expressions work
val = await FilterExpressions.eval("2+2");
- is(val, 4, "basic expression works");
+ equal(val, 4, "basic expression works");
// Test that multiline expressions work
val = await FilterExpressions.eval(`
2
+
2
`);
- is(val, 4, "multiline expression works");
+ equal(val, 4, "multiline expression works");
// Test that it reads from the context correctly.
val = await FilterExpressions.eval("first + second + 3", {first: 1, second: 2});
- is(val, 6, "context is available to filter expressions");
+ equal(val, 6, "context is available to filter expressions");
});
// Date tests
add_task(async function() {
let val;
// Test has a date transform
val = await FilterExpressions.eval('"2016-04-22"|date');
const d = new Date(Date.UTC(2016, 3, 22)); // months are 0 based
- is(val.toString(), d.toString(), "Date transform works");
+ equal(val.toString(), d.toString(), "Date transform works");
// Test dates are comparable
const context = {someTime: Date.UTC(2016, 0, 1)};
val = await FilterExpressions.eval('"2015-01-01"|date < someTime', context);
ok(val, "dates are comparable with less-than");
val = await FilterExpressions.eval('"2017-01-01"|date > someTime', context);
ok(val, "dates are comparable with greater-than");
});
@@ -61,17 +64,19 @@ add_task(async function() {
val = await FilterExpressions.eval('["test-4"]|bucketSample(0, 5, 10)');
ok(!val, "Bucket sample returns false for a known sample");
});
// Preference tests
add_task(async function() {
let val;
// Compare the value of the preference
- await SpecialPowers.pushPrefEnv({set: [["normandy.test.value", 3]]});
+ Services.prefs.setIntPref("normandy.test.value", 3);
+ registerCleanupFunction(() => Services.prefs.clearUserPref("normandy.test.value"));
+
val = await FilterExpressions.eval('"normandy.test.value"|preferenceValue == 3');
ok(val, "preferenceValue expression compares against preference values");
val = await FilterExpressions.eval('"normandy.test.value"|preferenceValue == "test"');
ok(!val, "preferenceValue expression fails value checks appropriately");
// preferenceValue can take a default value as an optional argument, which
// defaults to `undefined`.
val = await FilterExpressions.eval('"normandy.test.default"|preferenceValue(false) == false');
@@ -113,49 +118,49 @@ add_task(async function testKeys() {
new Set(["baz", "biff"]),
"keys returns the keys from an object in the context",
);
// Test that values from the prototype are not included
context = {ctxObject: Object.create({fooProto: 7})};
context.ctxObject.baz = 8;
context.ctxObject.biff = 5;
- is(
+ equal(
await FilterExpressions.eval("ctxObject.fooProto", context),
7,
"Prototype properties are accessible via property access",
);
val = await FilterExpressions.eval("ctxObject|keys", context);
Assert.deepEqual(
new Set(val),
new Set(["baz", "biff"]),
"keys does not return properties from the object's prototype chain",
);
// Return undefined for non-objects
- is(
+ equal(
await FilterExpressions.eval("ctxObject|keys", {ctxObject: 45}),
undefined,
"keys returns undefined for numbers",
);
- is(
+ equal(
await FilterExpressions.eval("ctxObject|keys", {ctxObject: null}),
undefined,
"keys returns undefined for null",
);
// Object properties are not cached
let pong = 0;
context = {ctxObject: {
get ping() {
return ++pong;
}
}};
await FilterExpressions.eval("ctxObject.ping == 0 || ctxObject.ping == 1", context);
- is(pong, 2, "Properties are not reifed");
+ equal(pong, 2, "Properties are not reifed");
});
// intersect tests
add_task(async function testIntersect() {
let val;
val = await FilterExpressions.eval("[1, 2, 3] intersect [4, 2, 6, 7, 3]");
Assert.deepEqual(
@@ -175,24 +180,24 @@ add_task(async function testIntersect()
val = await FilterExpressions.eval("['string', 2] intersect [4, 'string', 'other', 3]");
Assert.deepEqual(
new Set(val),
new Set(["string"]),
"intersect can compare strings",
);
// Return undefined when intersecting things that aren't lists.
- is(
+ equal(
await FilterExpressions.eval("5 intersect 7"),
undefined,
"intersect returns undefined for numbers",
);
- is(
+ equal(
await FilterExpressions.eval("val intersect other", {val: null, other: null}),
undefined,
"intersect returns undefined for null",
);
- is(
+ equal(
await FilterExpressions.eval("5 intersect [1, 2, 5]"),
undefined,
"intersect returns undefined if only one operand is a list",
);
});
rename from toolkit/components/normandy/test/unit/test_Sampling.js
rename to toolkit/components/utils/test/unit/test_Sampling.js
--- a/toolkit/components/normandy/test/unit/test_Sampling.js
+++ b/toolkit/components/utils/test/unit/test_Sampling.js
@@ -1,11 +1,12 @@
"use strict";
-ChromeUtils.import("resource://normandy/lib/Sampling.jsm", this);
+ChromeUtils.import("resource://gre/modules/components-utils/Sampling.jsm", this);
+
add_task(async function testStableSample() {
// Absolute samples
equal(await Sampling.stableSample("test", 1), true, "stableSample returns true for 100% sample");
equal(await Sampling.stableSample("test", 0), false, "stableSample returns false for 0% sample");
// Known samples. The numbers are nonces to make the tests pass
equal(await Sampling.stableSample("test-0", 0.5), true, "stableSample returns true for known matching sample");
new file mode 100644
--- /dev/null
+++ b/toolkit/components/utils/test/unit/xpcshell.ini
@@ -0,0 +1,2 @@
+[test_FilterExpressions.js]
+[test_Sampling.js]