From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- services/common/tests/unit/test_storage_adapter.js | 307 +++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 services/common/tests/unit/test_storage_adapter.js (limited to 'services/common/tests/unit/test_storage_adapter.js') diff --git a/services/common/tests/unit/test_storage_adapter.js b/services/common/tests/unit/test_storage_adapter.js new file mode 100644 index 0000000000..1dda35ad12 --- /dev/null +++ b/services/common/tests/unit/test_storage_adapter.js @@ -0,0 +1,307 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { Sqlite } = ChromeUtils.importESModule( + "resource://gre/modules/Sqlite.sys.mjs" +); +const { FirefoxAdapter } = ChromeUtils.importESModule( + "resource://services-common/kinto-storage-adapter.sys.mjs" +); + +// set up what we need to make storage adapters +const kintoFilename = "kinto.sqlite"; + +function do_get_kinto_connection() { + return FirefoxAdapter.openConnection({ path: kintoFilename }); +} + +function do_get_kinto_adapter(sqliteHandle) { + return new FirefoxAdapter("test", { sqliteHandle }); +} + +function do_get_kinto_db() { + let profile = do_get_profile(); + let kintoDB = profile.clone(); + kintoDB.append(kintoFilename); + return kintoDB; +} + +function cleanup_kinto() { + add_test(function cleanup_kinto_files() { + let kintoDB = do_get_kinto_db(); + // clean up the db + kintoDB.remove(false); + run_next_test(); + }); +} + +function test_collection_operations() { + add_task(async function test_kinto_clear() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + await adapter.clear(); + await sqliteHandle.close(); + }); + + // test creating new records... and getting them again + add_task(async function test_kinto_create_new_get_existing() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + let record = { id: "test-id", foo: "bar" }; + await adapter.execute(transaction => transaction.create(record)); + let newRecord = await adapter.get("test-id"); + // ensure the record is the same as when it was added + deepEqual(record, newRecord); + await sqliteHandle.close(); + }); + + // test removing records + add_task(async function test_kinto_can_remove_some_records() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + // create a second record + let record = { id: "test-id-2", foo: "baz" }; + await adapter.execute(transaction => transaction.create(record)); + let newRecord = await adapter.get("test-id-2"); + deepEqual(record, newRecord); + // delete the record + await adapter.execute(transaction => transaction.delete(record.id)); + newRecord = await adapter.get(record.id); + // ... and ensure it's no longer there + Assert.equal(newRecord, undefined); + // ensure the other record still exists + newRecord = await adapter.get("test-id"); + Assert.notEqual(newRecord, undefined); + await sqliteHandle.close(); + }); + + // test getting records that don't exist + add_task(async function test_kinto_get_non_existant() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + // Kinto expects adapters to either: + let newRecord = await adapter.get("missing-test-id"); + // resolve with an undefined record + Assert.equal(newRecord, undefined); + await sqliteHandle.close(); + }); + + // test updating records... and getting them again + add_task(async function test_kinto_update_get_existing() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + let originalRecord = { id: "test-id", foo: "bar" }; + let updatedRecord = { id: "test-id", foo: "baz" }; + await adapter.clear(); + await adapter.execute(transaction => transaction.create(originalRecord)); + await adapter.execute(transaction => transaction.update(updatedRecord)); + // ensure the record exists + let newRecord = await adapter.get("test-id"); + // ensure the record is the same as when it was added + deepEqual(updatedRecord, newRecord); + await sqliteHandle.close(); + }); + + // test listing records + add_task(async function test_kinto_list() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + let originalRecord = { id: "test-id-1", foo: "bar" }; + let records = await adapter.list(); + Assert.equal(records.length, 1); + await adapter.execute(transaction => transaction.create(originalRecord)); + records = await adapter.list(); + Assert.equal(records.length, 2); + await sqliteHandle.close(); + }); + + // test aborting transaction + add_task(async function test_kinto_aborting_transaction() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + await adapter.clear(); + let record = { id: 1, foo: "bar" }; + let error = null; + try { + await adapter.execute(transaction => { + transaction.create(record); + throw new Error("unexpected"); + }); + } catch (e) { + error = e; + } + Assert.notEqual(error, null); + let records = await adapter.list(); + Assert.equal(records.length, 0); + await sqliteHandle.close(); + }); + + // test save and get last modified + add_task(async function test_kinto_last_modified() { + const initialValue = 0; + const intendedValue = 12345678; + + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + let lastModified = await adapter.getLastModified(); + Assert.equal(lastModified, initialValue); + let result = await adapter.saveLastModified(intendedValue); + Assert.equal(result, intendedValue); + lastModified = await adapter.getLastModified(); + Assert.equal(lastModified, intendedValue); + + // test saveLastModified parses values correctly + result = await adapter.saveLastModified(" " + intendedValue + " blah"); + // should resolve with the parsed int + Assert.equal(result, intendedValue); + // and should have saved correctly + lastModified = await adapter.getLastModified(); + Assert.equal(lastModified, intendedValue); + await sqliteHandle.close(); + }); + + // test loadDump(records) + add_task(async function test_kinto_import_records() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + let record1 = { id: 1, foo: "bar" }; + let record2 = { id: 2, foo: "baz" }; + let impactedRecords = await adapter.loadDump([record1, record2]); + Assert.equal(impactedRecords.length, 2); + let newRecord1 = await adapter.get("1"); + // ensure the record is the same as when it was added + deepEqual(record1, newRecord1); + let newRecord2 = await adapter.get("2"); + // ensure the record is the same as when it was added + deepEqual(record2, newRecord2); + await sqliteHandle.close(); + }); + + add_task(async function test_kinto_import_records_should_override_existing() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + await adapter.clear(); + let records = await adapter.list(); + Assert.equal(records.length, 0); + let impactedRecords = await adapter.loadDump([ + { id: 1, foo: "bar" }, + { id: 2, foo: "baz" }, + ]); + Assert.equal(impactedRecords.length, 2); + await adapter.loadDump([ + { id: 1, foo: "baz" }, + { id: 3, foo: "bab" }, + ]); + records = await adapter.list(); + Assert.equal(records.length, 3); + let newRecord1 = await adapter.get("1"); + deepEqual(newRecord1.foo, "baz"); + await sqliteHandle.close(); + }); + + add_task(async function test_import_updates_lastModified() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + await adapter.loadDump([ + { id: 1, foo: "bar", last_modified: 1457896541 }, + { id: 2, foo: "baz", last_modified: 1458796542 }, + ]); + let lastModified = await adapter.getLastModified(); + Assert.equal(lastModified, 1458796542); + await sqliteHandle.close(); + }); + + add_task(async function test_import_preserves_older_lastModified() { + let sqliteHandle = await do_get_kinto_connection(); + let adapter = do_get_kinto_adapter(sqliteHandle); + await adapter.saveLastModified(1458796543); + + await adapter.loadDump([ + { id: 1, foo: "bar", last_modified: 1457896541 }, + { id: 2, foo: "baz", last_modified: 1458796542 }, + ]); + let lastModified = await adapter.getLastModified(); + Assert.equal(lastModified, 1458796543); + await sqliteHandle.close(); + }); + + add_task(async function test_save_metadata_preserves_lastModified() { + let sqliteHandle = await do_get_kinto_connection(); + + let adapter = do_get_kinto_adapter(sqliteHandle); + await adapter.saveLastModified(42); + + await adapter.saveMetadata({ id: "col" }); + + let lastModified = await adapter.getLastModified(); + Assert.equal(lastModified, 42); + await sqliteHandle.close(); + }); +} + +// test kinto db setup and operations in various scenarios +// test from scratch - no current existing database +add_test(function test_db_creation() { + add_test(function test_create_from_scratch() { + // ensure the file does not exist in the profile + let kintoDB = do_get_kinto_db(); + Assert.ok(!kintoDB.exists()); + run_next_test(); + }); + + test_collection_operations(); + + cleanup_kinto(); + run_next_test(); +}); + +// this is the closest we can get to a schema version upgrade at v1 - test an +// existing database +add_test(function test_creation_from_empty_db() { + add_test(function test_create_from_empty_db() { + // place an empty kinto db file in the profile + let profile = do_get_profile(); + + let emptyDB = do_get_file("test_storage_adapter/empty.sqlite"); + emptyDB.copyTo(profile, kintoFilename); + + run_next_test(); + }); + + test_collection_operations(); + + cleanup_kinto(); + run_next_test(); +}); + +// test schema version upgrade at v2 +add_test(function test_migration_from_v1_to_v2() { + add_test(function test_migrate_from_v1_to_v2() { + // place an empty kinto db file in the profile + let profile = do_get_profile(); + + let v1DB = do_get_file("test_storage_adapter/v1.sqlite"); + v1DB.copyTo(profile, kintoFilename); + + run_next_test(); + }); + + add_test(async function schema_is_update_from_1_to_2() { + // The `v1.sqlite` has schema version 1. + let sqliteHandle = await Sqlite.openConnection({ path: kintoFilename }); + Assert.equal(await sqliteHandle.getSchemaVersion(), 1); + await sqliteHandle.close(); + + // The `.openConnection()` migrates it to version 2. + sqliteHandle = await FirefoxAdapter.openConnection({ path: kintoFilename }); + Assert.equal(await sqliteHandle.getSchemaVersion(), 2); + await sqliteHandle.close(); + + run_next_test(); + }); + + test_collection_operations(); + + cleanup_kinto(); + run_next_test(); +}); -- cgit v1.2.3