test_bridged_engine.js (5441B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 const { BridgedEngine } = ChromeUtils.importESModule( 5 "resource://services-sync/bridged_engine.sys.mjs" 6 ); 7 const { Service } = ChromeUtils.importESModule( 8 "resource://services-sync/service.sys.mjs" 9 ); 10 11 add_task(async function test_interface() { 12 class TestBridge { 13 constructor() { 14 this.storageVersion = 2; 15 this.syncID = "syncID111111"; 16 this.clear(); 17 } 18 19 clear() { 20 this.lastSyncMillis = 0; 21 this.wasSyncStarted = false; 22 this.incomingEnvelopes = []; 23 this.uploadedIDs = []; 24 this.wasSyncFinished = false; 25 this.wasReset = false; 26 this.wasWiped = false; 27 } 28 29 // `mozIBridgedSyncEngine` methods. 30 31 lastSync() { 32 return this.lastSyncMillis; 33 } 34 35 setLastSync(millis) { 36 this.lastSyncMillis = millis; 37 } 38 39 resetSyncId() { 40 return this.syncID; 41 } 42 43 ensureCurrentSyncId(newSyncId) { 44 equal(newSyncId, this.syncID, "Local and new sync IDs should match"); 45 return this.syncID; 46 } 47 48 syncStarted() { 49 this.wasSyncStarted = true; 50 } 51 52 storeIncoming(envelopes) { 53 this.incomingEnvelopes.push(...envelopes.map(r => JSON.parse(r))); 54 } 55 56 apply() { 57 let outgoingEnvelopes = [ 58 { 59 id: "hanson", 60 data: { 61 plants: ["seed", "flower 💐", "rose"], 62 canYouTell: false, 63 }, 64 }, 65 { 66 id: "sheryl-crow", 67 data: { 68 today: "winding 🛣", 69 tomorrow: "winding 🛣", 70 }, 71 }, 72 ].map(cleartext => 73 JSON.stringify({ 74 id: cleartext.id, 75 payload: JSON.stringify(cleartext), 76 }) 77 ); 78 return outgoingEnvelopes; 79 } 80 81 setUploaded(millis, ids) { 82 this.uploadedIDs.push(...ids); 83 } 84 85 syncFinished() { 86 this.wasSyncFinished = true; 87 } 88 89 reset() { 90 this.clear(); 91 this.wasReset = true; 92 } 93 94 wipe() { 95 this.clear(); 96 this.wasWiped = true; 97 } 98 } 99 100 let bridge = new TestBridge(); 101 let engine = new BridgedEngine("Nineties", Service); 102 engine._bridge = bridge; 103 engine.enabled = true; 104 105 let server = await serverForFoo(engine); 106 try { 107 await SyncTestingInfrastructure(server); 108 109 info("Add server records"); 110 let foo = server.user("foo"); 111 let collection = foo.collection("nineties"); 112 let now = new_timestamp(); 113 collection.insert( 114 "backstreet", 115 encryptPayload({ 116 id: "backstreet", 117 data: { 118 say: "I want it that way", 119 when: "never", 120 }, 121 }), 122 now 123 ); 124 collection.insert( 125 "tlc", 126 encryptPayload({ 127 id: "tlc", 128 data: { 129 forbidden: ["scrubs 🚫"], 130 numberAvailable: false, 131 }, 132 }), 133 now + 5 134 ); 135 136 info("Sync the engine"); 137 // Advance the last sync time to skip the Backstreet Boys... 138 bridge.lastSyncMillis = 1000 * (now + 2); 139 await sync_engine_and_validate_telem(engine, false); 140 141 let metaGlobal = foo.collection("meta").wbo("global").get(); 142 deepEqual( 143 JSON.parse(metaGlobal.payload).engines.nineties, 144 { 145 version: 2, 146 syncID: "syncID111111", 147 }, 148 "Should write storage version and sync ID to m/g" 149 ); 150 151 greater(bridge.lastSyncMillis, 0, "Should update last sync time"); 152 ok( 153 bridge.wasSyncStarted, 154 "Should have started sync before storing incoming" 155 ); 156 deepEqual( 157 bridge.incomingEnvelopes 158 .sort((a, b) => a.id.localeCompare(b.id)) 159 .map(({ payload, ...envelope }) => ({ 160 cleartextAsObject: JSON.parse(payload), 161 ...envelope, 162 })), 163 [ 164 { 165 id: "tlc", 166 modified: now + 5, 167 cleartextAsObject: { 168 id: "tlc", 169 data: { 170 forbidden: ["scrubs 🚫"], 171 numberAvailable: false, 172 }, 173 }, 174 }, 175 ], 176 "Should stage incoming records from server" 177 ); 178 deepEqual( 179 bridge.uploadedIDs.sort(), 180 ["hanson", "sheryl-crow"], 181 "Should mark new local records as uploaded" 182 ); 183 ok(bridge.wasSyncFinished, "Should have finished sync after uploading"); 184 185 deepEqual( 186 collection.keys().sort(), 187 ["backstreet", "hanson", "sheryl-crow", "tlc"], 188 "Should have all records on server" 189 ); 190 let expectedRecords = [ 191 { 192 id: "sheryl-crow", 193 data: { 194 today: "winding 🛣", 195 tomorrow: "winding 🛣", 196 }, 197 }, 198 { 199 id: "hanson", 200 data: { 201 plants: ["seed", "flower 💐", "rose"], 202 canYouTell: false, 203 }, 204 }, 205 ]; 206 for (let expected of expectedRecords) { 207 let actual = collection.cleartext(expected.id); 208 deepEqual( 209 actual, 210 expected, 211 `Should upload record ${expected.id} from bridged engine` 212 ); 213 } 214 215 await engine.resetClient(); 216 ok(bridge.wasReset, "Should reset local storage for bridge"); 217 218 await engine.wipeClient(); 219 ok(bridge.wasWiped, "Should wipe local storage for bridge"); 220 221 await engine.resetSyncID(); 222 ok( 223 !foo.collection("nineties"), 224 "Should delete server collection after resetting sync ID" 225 ); 226 } finally { 227 await promiseStopServer(server); 228 await engine.finalize(); 229 } 230 });