diff options
Diffstat (limited to 'services/settings/test/unit/test_shutdown_handling.js')
-rw-r--r-- | services/settings/test/unit/test_shutdown_handling.js | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/services/settings/test/unit/test_shutdown_handling.js b/services/settings/test/unit/test_shutdown_handling.js new file mode 100644 index 0000000000..28a1765267 --- /dev/null +++ b/services/settings/test/unit/test_shutdown_handling.js @@ -0,0 +1,139 @@ +/* Any copyright is dedicated to the Public Domain. +http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { TestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TestUtils.sys.mjs" +); + +const { Database } = ChromeUtils.import( + "resource://services-settings/Database.jsm" +); +const { RemoteSettingsWorker } = ChromeUtils.import( + "resource://services-settings/RemoteSettingsWorker.jsm" +); +const { RemoteSettingsClient } = ChromeUtils.import( + "resource://services-settings/RemoteSettingsClient.jsm" +); + +add_task(async function test_shutdown_abort_after_start() { + // Start a forever transaction: + let counter = 0; + let transactionStarted; + let startedPromise = new Promise(r => { + transactionStarted = r; + }); + let promise = Database._executeIDB( + "records", + store => { + // Signal we've started. + transactionStarted(); + function makeRequest() { + if (++counter > 1000) { + Assert.ok( + false, + "We ran 1000 requests and didn't get aborted, what?" + ); + return; + } + dump("Making request " + counter + "\n"); + const request = store + .index("cid") + .openCursor(IDBKeyRange.only("foopydoo/foo")); + request.onsuccess = event => { + makeRequest(); + }; + } + makeRequest(); + }, + { mode: "readonly" } + ); + + // Wait for the transaction to start. + await startedPromise; + + Database._shutdownHandler(); // should abort the readonly transaction. + + let rejection; + await promise.catch(e => { + rejection = e; + }); + ok(rejection, "Promise should have rejected."); + + // Now clear the shutdown flag and rejection error: + Database._cancelShutdown(); + rejection = null; +}); + +add_task(async function test_shutdown_immediate_abort() { + // Now abort directly from the successful request. + let promise = Database._executeIDB( + "records", + store => { + let request = store + .index("cid") + .openCursor(IDBKeyRange.only("foopydoo/foo")); + request.onsuccess = event => { + // Abort immediately. + Database._shutdownHandler(); + request = store + .index("cid") + .openCursor(IDBKeyRange.only("foopydoo/foo")); + Assert.ok(false, "IndexedDB allowed opening a cursor after aborting?!"); + }; + }, + { mode: "readonly" } + ); + + let rejection; + // Wait for the abort + await promise.catch(e => { + rejection = e; + }); + ok(rejection, "Directly aborted promise should also have rejected."); + // Now clear the shutdown flag and rejection error: + Database._cancelShutdown(); +}); + +add_task(async function test_shutdown_worker() { + let client = new RemoteSettingsClient("language-dictionaries"); + const before = await client.get({ syncIfEmpty: false }); + Assert.equal(before.length, 0); + + let records = [{}]; + let importPromise = RemoteSettingsWorker._execute( + "_test_only_import", + ["main", "language-dictionaries", records, 0], + { mustComplete: true } + ); + let stringifyPromise = RemoteSettingsWorker.canonicalStringify( + [], + [], + Date.now() + ); + // Change the idle time so we shut the worker down even though we can't + // set gShutdown from outside of the worker management code. + Services.prefs.setIntPref( + "services.settings.worker_idle_max_milliseconds", + 1 + ); + RemoteSettingsWorker._abortCancelableRequests(); + await Assert.rejects( + stringifyPromise, + /Shutdown/, + "Should have aborted the stringify request at shutdown." + ); + await Assert.rejects( + importPromise, + /shutting down/, + "Ensure imports get aborted during shutdown" + ); + const after = await client.get({ syncIfEmpty: false }); + Assert.equal(after.length, 0); + await TestUtils.waitForCondition(() => !RemoteSettingsWorker.worker); + Assert.ok( + !RemoteSettingsWorker.worker, + "Worker should have been terminated." + ); +}); |