Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: appname == 'thunderbird'
- Manifest: services/settings/test/unit/xpcshell.toml
const { Database } = ChromeUtils.importESModule(
);
const { RemoteSettings } = ChromeUtils.importESModule(
);
let server;
let startupClients;
add_setup(async () => {
// Disable signature verification of collections listed in test startup.json.mzlz4
// since their metadata will eventually expire.
startupClients = [
"message-groups",
"nimbus-desktop-experiments",
"search-categorization",
"tracking-protection-lists",
"query-stripping",
"cfr",
].map(id => {
const c = RemoteSettings(id);
c.verifySignature = false;
return c;
});
// Setup an HTTP server to serve the 'startup.json.mzlz4' bundle.
server = new HttpServer();
server.start(-1);
server.registerDirectory(
"/cdn/bundles/",
do_get_file("test_remote_settings_startup_bundle")
);
server.registerPathHandler("/v1/", (request, response) => {
response.write(
JSON.stringify({
},
})
);
response.setHeader("Content-Type", "application/json; charset=UTF-8");
response.setStatusLine(null, 200, "OK");
});
Services.prefs.setStringPref(
"services.settings.server",
);
registerCleanupFunction(() => {
server.stop(() => {});
Services.prefs.clearUserPref("services.settings.loglevel");
});
});
async function clear_state() {
await Database.destroy();
RemoteSettings._ongoingExtractBundlePromise = null;
}
add_task(async function test_bundle_is_pulled_when_get_needs_sync() {
const client = startupClients[0];
Assert.ok(
!(await Utils.hasLocalDump(client.bucketName, client.collectionName)),
"Client has no packaged dump"
);
const records = await client.get();
Assert.equal(records.length, 6, "Records were read from startup bundle");
});
add_task(clear_state);
add_task(
async function test_signature_of_extracted_data_from_bundle_is_verified() {
const c = RemoteSettings("tracking-protection-lists"); // part of startup.json.mzlz4
c.verifySignature = true;
let called = null;
c.validateCollectionSignature = (records, timestamp, metadata) => {
called = { records, timestamp, metadata };
};
await c.get();
Assert.ok(!!called.records.length);
Assert.ok(called.timestamp >= 1694684362860);
Assert.ok(called.metadata.flags.includes("startup"));
}
);
add_task(clear_state);
add_task(async function test_bundle_is_not_importent_when_signature_fails() {
const c = RemoteSettings("tracking-protection-lists"); // part of startup.json.mzlz4
c.verifySignature = true;
let called = false;
c.validateCollectionSignature = () => {
called = true;
throw new Error("boom!");
};
let error;
try {
await c.get({ emptyListFallback: false });
Assert.ok(false, ".get() should fail without network");
} catch (e) {
error = e;
}
Assert.ok(called, "Signature was verified");
Assert.equal(
error.name,
"UnknownCollectionError",
".get() fails without network and with bad startup bundle"
);
});
add_task(clear_state);
add_task(async function test_sync_occurs_if_collection_not_part_of_bundle() {
const c = RemoteSettings("foo");
let error;
try {
await c.get({ emptyListFallback: false });
Assert.ok(false, ".get() should fail when bundle disabled");
} catch (e) {
error = e;
}
Assert.equal(
error.name,
"UnknownCollectionError",
".get() fails to sync data"
);
});
add_task(clear_state);
add_task(async function test_several_clients_wait_for_bundle() {
// several clients calling .get() in parallel will all take content from bundle.
const results = await Promise.allSettled(
startupClients.map(c => c.get({ emptyListFallback: false }))
);
Assert.deepEqual(
[6, 70, 5, "UnknownCollectionError", 3, 11],
results.map(({ status, value, reason }) =>
status == "fulfilled" ? value.length : reason.name
)
);
});
add_task(clear_state);