summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/head_dnr.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/head_dnr.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/head_dnr.js203
1 files changed, 203 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/head_dnr.js b/toolkit/components/extensions/test/xpcshell/head_dnr.js
new file mode 100644
index 0000000000..0c65869722
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/head_dnr.js
@@ -0,0 +1,203 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/* exported assertDNRStoreData, getDNRRule, getSchemaNormalizedRule, getSchemaNormalizedRules
+ */
+
+ChromeUtils.defineESModuleGetters(this, {
+ Schemas: "resource://gre/modules/Schemas.sys.mjs",
+});
+
+function getDNRRule({
+ id = 1,
+ priority = 1,
+ action = {},
+ condition = {},
+} = {}) {
+ return {
+ id,
+ priority,
+ action: {
+ type: "block",
+ ...action,
+ },
+ condition: {
+ ...condition,
+ },
+ };
+}
+
+const getSchemaNormalizedRule = (extensionTestWrapper, value) => {
+ const { extension } = extensionTestWrapper;
+ const validationContext = {
+ url: extension.baseURI.spec,
+ principal: extension.principal,
+ logError: err => {
+ // We don't expect this test helper function to be called on invalid rules,
+ // and so we trigger an explicit test failure if we ever hit any.
+ Assert.ok(
+ false,
+ `Unexpected logError on normalizing DNR rule ${JSON.stringify(
+ value
+ )} - ${err}`
+ );
+ },
+ preprocessors: {},
+ manifestVersion: extension.manifestVersion,
+ };
+
+ return Schemas.normalize(
+ value,
+ "declarativeNetRequest.Rule",
+ validationContext
+ );
+};
+
+const getSchemaNormalizedRules = (extensionTestWrapper, rules) => {
+ return rules.map(rule => {
+ const normalized = getSchemaNormalizedRule(extensionTestWrapper, rule);
+ if (normalized.error) {
+ throw new Error(
+ `Unexpected DNR Rule normalization error: ${normalized.error}`
+ );
+ }
+ return normalized.value;
+ });
+};
+
+const assertDNRStoreData = async (
+ dnrStore,
+ extensionTestWrapper,
+ expectedRulesets,
+ { assertIndividualRules = true } = {}
+) => {
+ const extUUID = extensionTestWrapper.uuid;
+ const rule_resources =
+ extensionTestWrapper.extension.manifest.declarative_net_request
+ ?.rule_resources;
+ const expectedRulesetIds = Array.from(Object.keys(expectedRulesets));
+ const expectedRulesetIndexesMap = expectedRulesetIds.reduce((acc, rsId) => {
+ acc.set(
+ rsId,
+ rule_resources.findIndex(rr => rr.id === rsId)
+ );
+ return acc;
+ }, new Map());
+
+ ok(
+ dnrStore._dataPromises.has(extUUID),
+ "Got promise for the test extension DNR data being loaded"
+ );
+
+ await dnrStore._dataPromises.get(extUUID);
+
+ ok(dnrStore._data.has(extUUID), "Got data for the test extension");
+
+ const dnrExtData = dnrStore._data.get(extUUID);
+ Assert.deepEqual(
+ {
+ schemaVersion: dnrExtData.schemaVersion,
+ extVersion: dnrExtData.extVersion,
+ },
+ {
+ schemaVersion: dnrExtData.constructor.VERSION,
+ extVersion: extensionTestWrapper.extension.version,
+ },
+ "Got the expected data schema version and extension version in the store data"
+ );
+ Assert.deepEqual(
+ Array.from(dnrExtData.staticRulesets.keys()),
+ expectedRulesetIds,
+ "Got the enabled rulesets in the stored data staticRulesets Map"
+ );
+
+ for (const rulesetId of expectedRulesetIds) {
+ const expectedRulesetIdx = expectedRulesetIndexesMap.get(rulesetId);
+ const expectedRulesetRules = getSchemaNormalizedRules(
+ extensionTestWrapper,
+ expectedRulesets[rulesetId]
+ );
+ const actualData = dnrExtData.staticRulesets.get(rulesetId);
+ equal(
+ actualData.idx,
+ expectedRulesetIdx,
+ `Got the expected ruleset index for ruleset id ${rulesetId}`
+ );
+
+ // Asserting an entire array of rules all at once will produce
+ // a big enough output to don't be immediately useful to investigate
+ // failures, asserting each rule individually would produce more
+ // readable assertion failure logs.
+ const assertRuleAtIdx = ruleIdx => {
+ const actualRule = actualData.rules[ruleIdx];
+ const expectedRule = expectedRulesetRules[ruleIdx];
+ Assert.deepEqual(
+ actualRule,
+ expectedRule,
+ `Got the expected rule at index ${ruleIdx} for ruleset id "${rulesetId}"`
+ );
+ Assert.equal(
+ actualRule.constructor.name,
+ "Rule",
+ `Expect rule at index ${ruleIdx} to be an instance of the Rule class`
+ );
+ if (expectedRule.condition.regexFilter) {
+ const compiledRegexFilter =
+ actualData.rules[ruleIdx].condition.getCompiledRegexFilter();
+ Assert.equal(
+ compiledRegexFilter?.constructor.name,
+ "RegExp",
+ `Expect rule ${ruleIdx} condition.getCompiledRegexFilter() to return a compiled regexp filter`
+ );
+ Assert.equal(
+ compiledRegexFilter?.source,
+ new RegExp(expectedRule.condition.regexFilter).source,
+ `Expect rule ${ruleIdx} condition's compiled RegExp source to match the regexFilter string`
+ );
+ Assert.equal(
+ compiledRegexFilter?.ignoreCase,
+ !expectedRule.condition.isUrlFilterCaseSensitive,
+ `Expect rule ${ruleIdx} conditions's compiled RegExp ignoreCase to be set based on condition.isUrlFilterCaseSensitive`
+ );
+ }
+ };
+
+ // Some tests may be using a big enough number of rules that
+ // the assertiongs would be producing a huge amount of log spam,
+ // and so for those tests we only explicitly assert the first
+ // and last rule and that the total amount of rules matches the
+ // expected number of rules (there are still other tests explicitly
+ // asserting all loaded rules).
+ if (assertIndividualRules) {
+ info(`Verify each individual rule loaded for ruleset id "${rulesetId}"`);
+ for (let ruleIdx = 0; ruleIdx < expectedRulesetRules.length; ruleIdx++) {
+ assertRuleAtIdx(ruleIdx);
+ }
+ } else if (expectedRulesetRules.length) {
+ // NOTE: Only asserting the first and last rule also helps to speed up
+ // the test is some slower builds when the number of expected rules is
+ // big enough (e.g. the test task verifying the enforced rule count limits
+ // was timing out in tsan build because asserting all indidual rules was
+ // taking long enough and the event page was being suspended on the idle
+ // timeout by the time we did run all these assertion and proceeding with
+ // the rest of the test task assertions), we still confirm that the total
+ // number of expected vs actual rules also matches right after these
+ // assertions.
+ info(
+ `Verify the first and last rules loaded for ruleset id "${rulesetId}"`
+ );
+ const lastExpectedRuleIdx = expectedRulesetRules.length - 1;
+ for (const ruleIdx of [0, lastExpectedRuleIdx]) {
+ assertRuleAtIdx(ruleIdx);
+ }
+ }
+
+ equal(
+ actualData.rules.length,
+ expectedRulesetRules.length,
+ `Got the expected number of rules loaded for ruleset id "${rulesetId}"`
+ );
+ }
+};