diff options
Diffstat (limited to 'services/sync/tests/unit/test_tab_engine.js')
-rw-r--r-- | services/sync/tests/unit/test_tab_engine.js | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/services/sync/tests/unit/test_tab_engine.js b/services/sync/tests/unit/test_tab_engine.js new file mode 100644 index 0000000000..0a96a8f4d6 --- /dev/null +++ b/services/sync/tests/unit/test_tab_engine.js @@ -0,0 +1,220 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { TabProvider } = ChromeUtils.import( + "resource://services-sync/engines/tabs.js" +); +const { WBORecord } = ChromeUtils.import("resource://services-sync/record.js"); +const { Service } = ChromeUtils.import("resource://services-sync/service.js"); + +let engine; +// We'll need the clients engine for testing as tabs is closely related +let clientsEngine; + +async function syncClientsEngine(server) { + clientsEngine._lastFxADevicesFetch = 0; + clientsEngine.lastModified = server.getCollection("foo", "clients").timestamp; + await clientsEngine._sync(); +} + +async function makeRemoteClients() { + let server = await serverForFoo(clientsEngine); + await configureIdentity({ username: "foo" }, server); + await Service.login(); + + await SyncTestingInfrastructure(server); + await generateNewKeys(Service.collectionKeys); + + let remoteId = Utils.makeGUID(); + let remoteId2 = Utils.makeGUID(); + let collection = server.getCollection("foo", "clients"); + + _("Create remote client records"); + collection.insertRecord({ + id: remoteId, + name: "Remote client", + type: "desktop", + commands: [], + version: "48", + fxaDeviceId: remoteId, + fxaDeviceName: "Fxa - Remote client", + protocols: ["1.5"], + }); + + collection.insertRecord({ + id: remoteId2, + name: "Remote client 2", + type: "desktop", + commands: [], + version: "48", + fxaDeviceId: remoteId2, + fxaDeviceName: "Fxa - Remote client 2", + protocols: ["1.5"], + }); + + let fxAccounts = clientsEngine.fxAccounts; + clientsEngine.fxAccounts = { + notifyDevices() { + return Promise.resolve(true); + }, + device: { + getLocalId() { + return fxAccounts.device.getLocalId(); + }, + getLocalName() { + return fxAccounts.device.getLocalName(); + }, + getLocalType() { + return fxAccounts.device.getLocalType(); + }, + recentDeviceList: [{ id: remoteId, name: "remote device" }], + refreshDeviceList() { + return Promise.resolve(true); + }, + }, + _internal: { + now() { + return Date.now(); + }, + }, + }; + + await syncClientsEngine(server); +} + +add_task(async function setup() { + clientsEngine = Service.clientsEngine; + // Make some clients to test with + await makeRemoteClients(); + + // Make the tabs engine for all the tests to use + engine = Service.engineManager.get("tabs"); + await engine.initialize(); + + // Since these are xpcshell tests, we'll need to mock this + TabProvider.shouldSkipWindow = mockShouldSkipWindow; +}); + +add_task(async function test_tab_engine_skips_incoming_local_record() { + _("Ensure incoming records that match local client ID are never applied."); + + let localID = clientsEngine.localID; + let collection = new ServerCollection(); + + _("Creating remote tab record with local client ID"); + let localRecord = encryptPayload({ + id: localID, + clientName: "local", + tabs: [ + { + title: "title", + urlHistory: ["http://foo.com/"], + icon: "", + lastUsed: 2000, + }, + ], + }); + collection.insert(localID, localRecord); + + _("Creating remote tab record with a different client ID"); + let remoteID = "fake-guid-00"; // remote should match one of the test clients + let remoteRecord = encryptPayload({ + id: remoteID, + clientName: "not local", + tabs: [ + { + title: "title2", + urlHistory: ["http://bar.com/"], + icon: "", + lastUsed: 3000, + }, + ], + }); + collection.insert(remoteID, remoteRecord); + + _("Setting up Sync server"); + let server = sync_httpd_setup({ + "/1.1/foo/storage/tabs": collection.handler(), + }); + + await SyncTestingInfrastructure(server); + + let syncID = await engine.resetLocalSyncID(); + let meta_global = Service.recordManager.set( + engine.metaURL, + new WBORecord(engine.metaURL) + ); + meta_global.payload.engines = { + tabs: { version: engine.version, syncID }, + }; + + await generateNewKeys(Service.collectionKeys); + + let promiseFinished = new Promise(resolve => { + let syncFinish = engine._syncFinish; + engine._syncFinish = async function() { + let remoteTabs = await engine._rustStore.getAll(); + equal( + remoteTabs.length, + 1, + "Remote client record was applied and local wasn't" + ); + let record = remoteTabs[0]; + equal(record.clientId, remoteID, "Remote client ID matches"); + + _("Ensure getAllClients returns the correct shape"); + let clients = await engine.getAllClients(); + equal(clients.length, 1); + let client = clients[0]; + equal(client.id, "fake-guid-00"); + equal(client.name, "Remote client"); + equal(client.type, "desktop"); + Assert.ok(client.lastModified); // lastModified should be filled in once serverModified is populated from the server + deepEqual(client.tabs, [ + { + title: "title2", + urlHistory: ["http://bar.com/"], + icon: "", + lastUsed: 3000, + }, + ]); + await syncFinish.call(engine); + resolve(); + }; + }); + + _("Start sync"); + Service.scheduler.hasIncomingItems = false; + await engine._sync(); + await promiseFinished; + // Bug 1800185 - we don't want the sync scheduler to see these records as incoming. + Assert.ok(!Service.scheduler.hasIncomingItems); +}); + +// Ensure we trim tabs in the case of going past the max payload size allowed +add_task(async function test_too_many_tabs() { + let a_lot_of_tabs = []; + + for (let i = 0; i < 4000; ++i) { + a_lot_of_tabs.push( + `http://example${i}.com/some-super-long-url-chain-to-help-with-bytes` + ); + } + + TabProvider.getWindowEnumerator = mockGetWindowEnumerator.bind( + this, + a_lot_of_tabs + ); + + let encoder = Utils.utf8Encoder; + // see tryfitItems(..) in util.js + const computeSerializedSize = records => + encoder.encode(JSON.stringify(records)).byteLength; + + const maxPayloadSize = Service.getMaxRecordPayloadSize(); + // We are over max payload size + Assert.ok(computeSerializedSize(a_lot_of_tabs) > maxPayloadSize); + let tabs = await engine.getTabsWithinPayloadSize(); + // We are now under max payload size + Assert.ok(computeSerializedSize(tabs) < maxPayloadSize); +}); |