OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """Tests exercising chromiumsync and SyncDataModel.""" | |
7 | |
8 import pickle | |
9 import unittest | |
10 | |
11 import autofill_specifics_pb2 | |
12 import bookmark_specifics_pb2 | |
13 import chromiumsync | |
14 import managed_user_specifics_pb2 | |
15 import sync_pb2 | |
16 import theme_specifics_pb2 | |
17 | |
18 class SyncDataModelTest(unittest.TestCase): | |
19 def setUp(self): | |
20 self.model = chromiumsync.SyncDataModel() | |
21 # The Synced Bookmarks folder is not created by default | |
22 self._expect_synced_bookmarks_folder = False | |
23 | |
24 def AddToModel(self, proto): | |
25 self.model._entries[proto.id_string] = proto | |
26 | |
27 def GetChangesFromTimestamp(self, requested_types, timestamp): | |
28 message = sync_pb2.GetUpdatesMessage() | |
29 message.from_timestamp = timestamp | |
30 for data_type in requested_types: | |
31 getattr(message.requested_types, | |
32 chromiumsync.SYNC_TYPE_TO_DESCRIPTOR[ | |
33 data_type].name).SetInParent() | |
34 return self.model.GetChanges( | |
35 chromiumsync.UpdateSieve(message, self.model.migration_history)) | |
36 | |
37 def FindMarkerByNumber(self, markers, datatype): | |
38 """Search a list of progress markers and find the one for a datatype.""" | |
39 for marker in markers: | |
40 if marker.data_type_id == datatype.number: | |
41 return marker | |
42 self.fail('Required marker not found: %s' % datatype.name) | |
43 | |
44 def testPermanentItemSpecs(self): | |
45 specs = chromiumsync.SyncDataModel._PERMANENT_ITEM_SPECS | |
46 | |
47 declared_specs = set(['0']) | |
48 for spec in specs: | |
49 self.assertTrue(spec.parent_tag in declared_specs, 'parent tags must ' | |
50 'be declared before use') | |
51 declared_specs.add(spec.tag) | |
52 | |
53 unique_datatypes = set([x.sync_type for x in specs]) | |
54 self.assertEqual(unique_datatypes, | |
55 set(chromiumsync.ALL_TYPES[1:]), | |
56 'Every sync datatype should have a permanent folder ' | |
57 'associated with it') | |
58 | |
59 def testSaveEntry(self): | |
60 proto = sync_pb2.SyncEntity() | |
61 proto.id_string = 'abcd' | |
62 proto.version = 0 | |
63 self.assertFalse(self.model._ItemExists(proto.id_string)) | |
64 self.model._SaveEntry(proto) | |
65 self.assertEqual(1, proto.version) | |
66 self.assertTrue(self.model._ItemExists(proto.id_string)) | |
67 self.model._SaveEntry(proto) | |
68 self.assertEqual(2, proto.version) | |
69 proto.version = 0 | |
70 self.assertTrue(self.model._ItemExists(proto.id_string)) | |
71 self.assertEqual(2, self.model._entries[proto.id_string].version) | |
72 | |
73 def testCreatePermanentItems(self): | |
74 self.model._CreateDefaultPermanentItems(chromiumsync.ALL_TYPES) | |
75 self.assertEqual(len(chromiumsync.ALL_TYPES) + 1, | |
76 len(self.model._entries)) | |
77 | |
78 def ExpectedPermanentItemCount(self, sync_type): | |
79 if sync_type == chromiumsync.BOOKMARK: | |
80 if self._expect_synced_bookmarks_folder: | |
81 return 4 | |
82 else: | |
83 return 3 | |
84 else: | |
85 return 1 | |
86 | |
87 def testGetChangesFromTimestampZeroForEachType(self): | |
88 all_types = chromiumsync.ALL_TYPES[1:] | |
89 for sync_type in all_types: | |
90 self.model = chromiumsync.SyncDataModel() | |
91 request_types = [sync_type] | |
92 | |
93 version, changes, remaining = ( | |
94 self.GetChangesFromTimestamp(request_types, 0)) | |
95 | |
96 expected_count = self.ExpectedPermanentItemCount(sync_type) | |
97 self.assertEqual(expected_count, version) | |
98 self.assertEqual(expected_count, len(changes)) | |
99 for change in changes: | |
100 self.assertTrue(change.HasField('server_defined_unique_tag')) | |
101 self.assertEqual(change.version, change.sync_timestamp) | |
102 self.assertTrue(change.version <= version) | |
103 | |
104 # Test idempotence: another GetUpdates from ts=0 shouldn't recreate. | |
105 version, changes, remaining = ( | |
106 self.GetChangesFromTimestamp(request_types, 0)) | |
107 self.assertEqual(expected_count, version) | |
108 self.assertEqual(expected_count, len(changes)) | |
109 self.assertEqual(0, remaining) | |
110 | |
111 # Doing a wider GetUpdates from timestamp zero shouldn't recreate either. | |
112 new_version, changes, remaining = ( | |
113 self.GetChangesFromTimestamp(all_types, 0)) | |
114 if self._expect_synced_bookmarks_folder: | |
115 self.assertEqual(len(chromiumsync.SyncDataModel._PERMANENT_ITEM_SPECS), | |
116 new_version) | |
117 else: | |
118 self.assertEqual( | |
119 len(chromiumsync.SyncDataModel._PERMANENT_ITEM_SPECS) -1, | |
120 new_version) | |
121 self.assertEqual(new_version, len(changes)) | |
122 self.assertEqual(0, remaining) | |
123 version, changes, remaining = ( | |
124 self.GetChangesFromTimestamp(request_types, 0)) | |
125 self.assertEqual(new_version, version) | |
126 self.assertEqual(expected_count, len(changes)) | |
127 self.assertEqual(0, remaining) | |
128 | |
129 def testBatchSize(self): | |
130 for sync_type in chromiumsync.ALL_TYPES[1:]: | |
131 specifics = chromiumsync.GetDefaultEntitySpecifics(sync_type) | |
132 self.model = chromiumsync.SyncDataModel() | |
133 request_types = [sync_type] | |
134 | |
135 for i in range(self.model._BATCH_SIZE*3): | |
136 entry = sync_pb2.SyncEntity() | |
137 entry.id_string = 'batch test %d' % i | |
138 entry.specifics.CopyFrom(specifics) | |
139 self.model._SaveEntry(entry) | |
140 last_bit = self.ExpectedPermanentItemCount(sync_type) | |
141 version, changes, changes_remaining = ( | |
142 self.GetChangesFromTimestamp(request_types, 0)) | |
143 self.assertEqual(self.model._BATCH_SIZE, version) | |
144 self.assertEqual(self.model._BATCH_SIZE*2 + last_bit, changes_remaining) | |
145 version, changes, changes_remaining = ( | |
146 self.GetChangesFromTimestamp(request_types, version)) | |
147 self.assertEqual(self.model._BATCH_SIZE*2, version) | |
148 self.assertEqual(self.model._BATCH_SIZE + last_bit, changes_remaining) | |
149 version, changes, changes_remaining = ( | |
150 self.GetChangesFromTimestamp(request_types, version)) | |
151 self.assertEqual(self.model._BATCH_SIZE*3, version) | |
152 self.assertEqual(last_bit, changes_remaining) | |
153 version, changes, changes_remaining = ( | |
154 self.GetChangesFromTimestamp(request_types, version)) | |
155 self.assertEqual(self.model._BATCH_SIZE*3 + last_bit, version) | |
156 self.assertEqual(0, changes_remaining) | |
157 | |
158 # Now delete a third of the items. | |
159 for i in xrange(self.model._BATCH_SIZE*3 - 1, 0, -3): | |
160 entry = sync_pb2.SyncEntity() | |
161 entry.id_string = 'batch test %d' % i | |
162 entry.deleted = True | |
163 self.model._SaveEntry(entry) | |
164 | |
165 # The batch counts shouldn't change. | |
166 version, changes, changes_remaining = ( | |
167 self.GetChangesFromTimestamp(request_types, 0)) | |
168 self.assertEqual(self.model._BATCH_SIZE, len(changes)) | |
169 self.assertEqual(self.model._BATCH_SIZE*2 + last_bit, changes_remaining) | |
170 version, changes, changes_remaining = ( | |
171 self.GetChangesFromTimestamp(request_types, version)) | |
172 self.assertEqual(self.model._BATCH_SIZE, len(changes)) | |
173 self.assertEqual(self.model._BATCH_SIZE + last_bit, changes_remaining) | |
174 version, changes, changes_remaining = ( | |
175 self.GetChangesFromTimestamp(request_types, version)) | |
176 self.assertEqual(self.model._BATCH_SIZE, len(changes)) | |
177 self.assertEqual(last_bit, changes_remaining) | |
178 version, changes, changes_remaining = ( | |
179 self.GetChangesFromTimestamp(request_types, version)) | |
180 self.assertEqual(last_bit, len(changes)) | |
181 self.assertEqual(self.model._BATCH_SIZE*4 + last_bit, version) | |
182 self.assertEqual(0, changes_remaining) | |
183 | |
184 def testCommitEachDataType(self): | |
185 for sync_type in chromiumsync.ALL_TYPES[1:]: | |
186 specifics = chromiumsync.GetDefaultEntitySpecifics(sync_type) | |
187 self.model = chromiumsync.SyncDataModel() | |
188 my_cache_guid = '112358132134' | |
189 parent = 'foobar' | |
190 commit_session = {} | |
191 | |
192 # Start with a GetUpdates from timestamp 0, to populate permanent items. | |
193 original_version, original_changes, changes_remaining = ( | |
194 self.GetChangesFromTimestamp([sync_type], 0)) | |
195 | |
196 def DoCommit(original=None, id_string='', name=None, parent=None, | |
197 position=0): | |
198 proto = sync_pb2.SyncEntity() | |
199 if original is not None: | |
200 proto.version = original.version | |
201 proto.id_string = original.id_string | |
202 proto.parent_id_string = original.parent_id_string | |
203 proto.name = original.name | |
204 else: | |
205 proto.id_string = id_string | |
206 proto.version = 0 | |
207 proto.specifics.CopyFrom(specifics) | |
208 if name is not None: | |
209 proto.name = name | |
210 if parent: | |
211 proto.parent_id_string = parent.id_string | |
212 proto.insert_after_item_id = 'please discard' | |
213 proto.position_in_parent = position | |
214 proto.folder = True | |
215 proto.deleted = False | |
216 result = self.model.CommitEntry(proto, my_cache_guid, commit_session) | |
217 self.assertTrue(result) | |
218 return (proto, result) | |
219 | |
220 # Commit a new item. | |
221 proto1, result1 = DoCommit(name='namae', id_string='Foo', | |
222 parent=original_changes[-1], position=100) | |
223 # Commit an item whose parent is another item (referenced via the | |
224 # pre-commit ID). | |
225 proto2, result2 = DoCommit(name='Secondo', id_string='Bar', | |
226 parent=proto1, position=-100) | |
227 # Commit a sibling of the second item. | |
228 proto3, result3 = DoCommit(name='Third!', id_string='Baz', | |
229 parent=proto1, position=-50) | |
230 | |
231 self.assertEqual(3, len(commit_session)) | |
232 for p, r in [(proto1, result1), (proto2, result2), (proto3, result3)]: | |
233 self.assertNotEqual(r.id_string, p.id_string) | |
234 self.assertEqual(r.originator_client_item_id, p.id_string) | |
235 self.assertEqual(r.originator_cache_guid, my_cache_guid) | |
236 self.assertTrue(r is not self.model._entries[r.id_string], | |
237 "Commit result didn't make a defensive copy.") | |
238 self.assertTrue(p is not self.model._entries[r.id_string], | |
239 "Commit result didn't make a defensive copy.") | |
240 self.assertEqual(commit_session.get(p.id_string), r.id_string) | |
241 self.assertTrue(r.version > original_version) | |
242 self.assertEqual(result1.parent_id_string, proto1.parent_id_string) | |
243 self.assertEqual(result2.parent_id_string, result1.id_string) | |
244 version, changes, remaining = ( | |
245 self.GetChangesFromTimestamp([sync_type], original_version)) | |
246 self.assertEqual(3, len(changes)) | |
247 self.assertEqual(0, remaining) | |
248 self.assertEqual(original_version + 3, version) | |
249 self.assertEqual([result1, result2, result3], changes) | |
250 for c in changes: | |
251 self.assertTrue(c is not self.model._entries[c.id_string], | |
252 "GetChanges didn't make a defensive copy.") | |
253 self.assertTrue(result2.position_in_parent < result3.position_in_parent) | |
254 self.assertEqual(-100, result2.position_in_parent) | |
255 | |
256 # Now update the items so that the second item is the parent of the | |
257 # first; with the first sandwiched between two new items (4 and 5). | |
258 # Do this in a new commit session, meaning we'll reference items from | |
259 # the first batch by their post-commit, server IDs. | |
260 commit_session = {} | |
261 old_cache_guid = my_cache_guid | |
262 my_cache_guid = 'A different GUID' | |
263 proto2b, result2b = DoCommit(original=result2, | |
264 parent=original_changes[-1]) | |
265 proto4, result4 = DoCommit(id_string='ID4', name='Four', | |
266 parent=result2, position=-200) | |
267 proto1b, result1b = DoCommit(original=result1, | |
268 parent=result2, position=-150) | |
269 proto5, result5 = DoCommit(id_string='ID5', name='Five', parent=result2, | |
270 position=150) | |
271 | |
272 self.assertEqual(2, len(commit_session), 'Only new items in second ' | |
273 'batch should be in the session') | |
274 for p, r, original in [(proto2b, result2b, proto2), | |
275 (proto4, result4, proto4), | |
276 (proto1b, result1b, proto1), | |
277 (proto5, result5, proto5)]: | |
278 self.assertEqual(r.originator_client_item_id, original.id_string) | |
279 if original is not p: | |
280 self.assertEqual(r.id_string, p.id_string, | |
281 'Ids should be stable after first commit') | |
282 self.assertEqual(r.originator_cache_guid, old_cache_guid) | |
283 else: | |
284 self.assertNotEqual(r.id_string, p.id_string) | |
285 self.assertEqual(r.originator_cache_guid, my_cache_guid) | |
286 self.assertEqual(commit_session.get(p.id_string), r.id_string) | |
287 self.assertTrue(r is not self.model._entries[r.id_string], | |
288 "Commit result didn't make a defensive copy.") | |
289 self.assertTrue(p is not self.model._entries[r.id_string], | |
290 "Commit didn't make a defensive copy.") | |
291 self.assertTrue(r.version > p.version) | |
292 version, changes, remaining = ( | |
293 self.GetChangesFromTimestamp([sync_type], original_version)) | |
294 self.assertEqual(5, len(changes)) | |
295 self.assertEqual(0, remaining) | |
296 self.assertEqual(original_version + 7, version) | |
297 self.assertEqual([result3, result2b, result4, result1b, result5], changes) | |
298 for c in changes: | |
299 self.assertTrue(c is not self.model._entries[c.id_string], | |
300 "GetChanges didn't make a defensive copy.") | |
301 self.assertTrue(result4.parent_id_string == | |
302 result1b.parent_id_string == | |
303 result5.parent_id_string == | |
304 result2b.id_string) | |
305 self.assertTrue(result4.position_in_parent < | |
306 result1b.position_in_parent < | |
307 result5.position_in_parent) | |
308 | |
309 def testUpdateSieve(self): | |
310 # from_timestamp, legacy mode | |
311 autofill = chromiumsync.SYNC_TYPE_FIELDS['autofill'] | |
312 theme = chromiumsync.SYNC_TYPE_FIELDS['theme'] | |
313 msg = sync_pb2.GetUpdatesMessage() | |
314 msg.from_timestamp = 15412 | |
315 msg.requested_types.autofill.SetInParent() | |
316 msg.requested_types.theme.SetInParent() | |
317 | |
318 sieve = chromiumsync.UpdateSieve(msg) | |
319 self.assertEqual(sieve._state, | |
320 {chromiumsync.TOP_LEVEL: 15412, | |
321 chromiumsync.AUTOFILL: 15412, | |
322 chromiumsync.THEME: 15412}) | |
323 | |
324 response = sync_pb2.GetUpdatesResponse() | |
325 sieve.SaveProgress(15412, response) | |
326 self.assertEqual(0, len(response.new_progress_marker)) | |
327 self.assertFalse(response.HasField('new_timestamp')) | |
328 | |
329 response = sync_pb2.GetUpdatesResponse() | |
330 sieve.SaveProgress(15413, response) | |
331 self.assertEqual(0, len(response.new_progress_marker)) | |
332 self.assertTrue(response.HasField('new_timestamp')) | |
333 self.assertEqual(15413, response.new_timestamp) | |
334 | |
335 # Existing tokens | |
336 msg = sync_pb2.GetUpdatesMessage() | |
337 marker = msg.from_progress_marker.add() | |
338 marker.data_type_id = autofill.number | |
339 marker.token = pickle.dumps((15412, 1)) | |
340 marker = msg.from_progress_marker.add() | |
341 marker.data_type_id = theme.number | |
342 marker.token = pickle.dumps((15413, 1)) | |
343 sieve = chromiumsync.UpdateSieve(msg) | |
344 self.assertEqual(sieve._state, | |
345 {chromiumsync.TOP_LEVEL: 15412, | |
346 chromiumsync.AUTOFILL: 15412, | |
347 chromiumsync.THEME: 15413}) | |
348 | |
349 response = sync_pb2.GetUpdatesResponse() | |
350 sieve.SaveProgress(15413, response) | |
351 self.assertEqual(1, len(response.new_progress_marker)) | |
352 self.assertFalse(response.HasField('new_timestamp')) | |
353 marker = response.new_progress_marker[0] | |
354 self.assertEqual(marker.data_type_id, autofill.number) | |
355 self.assertEqual(pickle.loads(marker.token), (15413, 1)) | |
356 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
357 | |
358 # Empty tokens indicating from timestamp = 0 | |
359 msg = sync_pb2.GetUpdatesMessage() | |
360 marker = msg.from_progress_marker.add() | |
361 marker.data_type_id = autofill.number | |
362 marker.token = pickle.dumps((412, 1)) | |
363 marker = msg.from_progress_marker.add() | |
364 marker.data_type_id = theme.number | |
365 marker.token = '' | |
366 sieve = chromiumsync.UpdateSieve(msg) | |
367 self.assertEqual(sieve._state, | |
368 {chromiumsync.TOP_LEVEL: 0, | |
369 chromiumsync.AUTOFILL: 412, | |
370 chromiumsync.THEME: 0}) | |
371 response = sync_pb2.GetUpdatesResponse() | |
372 sieve.SaveProgress(1, response) | |
373 self.assertEqual(1, len(response.new_progress_marker)) | |
374 self.assertFalse(response.HasField('new_timestamp')) | |
375 marker = response.new_progress_marker[0] | |
376 self.assertEqual(marker.data_type_id, theme.number) | |
377 self.assertEqual(pickle.loads(marker.token), (1, 1)) | |
378 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
379 | |
380 response = sync_pb2.GetUpdatesResponse() | |
381 sieve.SaveProgress(412, response) | |
382 self.assertEqual(1, len(response.new_progress_marker)) | |
383 self.assertFalse(response.HasField('new_timestamp')) | |
384 marker = response.new_progress_marker[0] | |
385 self.assertEqual(marker.data_type_id, theme.number) | |
386 self.assertEqual(pickle.loads(marker.token), (412, 1)) | |
387 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
388 | |
389 response = sync_pb2.GetUpdatesResponse() | |
390 sieve.SaveProgress(413, response) | |
391 self.assertEqual(2, len(response.new_progress_marker)) | |
392 self.assertFalse(response.HasField('new_timestamp')) | |
393 marker = self.FindMarkerByNumber(response.new_progress_marker, theme) | |
394 self.assertEqual(pickle.loads(marker.token), (413, 1)) | |
395 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
396 marker = self.FindMarkerByNumber(response.new_progress_marker, autofill) | |
397 self.assertEqual(pickle.loads(marker.token), (413, 1)) | |
398 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
399 | |
400 # Migration token timestamps (client gives timestamp, server returns token) | |
401 # These are for migrating from the old 'timestamp' protocol to the | |
402 # progressmarker protocol, and have nothing to do with the MIGRATION_DONE | |
403 # error code. | |
404 msg = sync_pb2.GetUpdatesMessage() | |
405 marker = msg.from_progress_marker.add() | |
406 marker.data_type_id = autofill.number | |
407 marker.timestamp_token_for_migration = 15213 | |
408 marker = msg.from_progress_marker.add() | |
409 marker.data_type_id = theme.number | |
410 marker.timestamp_token_for_migration = 15211 | |
411 sieve = chromiumsync.UpdateSieve(msg) | |
412 self.assertEqual(sieve._state, | |
413 {chromiumsync.TOP_LEVEL: 15211, | |
414 chromiumsync.AUTOFILL: 15213, | |
415 chromiumsync.THEME: 15211}) | |
416 response = sync_pb2.GetUpdatesResponse() | |
417 sieve.SaveProgress(16000, response) # There were updates | |
418 self.assertEqual(2, len(response.new_progress_marker)) | |
419 self.assertFalse(response.HasField('new_timestamp')) | |
420 marker = self.FindMarkerByNumber(response.new_progress_marker, theme) | |
421 self.assertEqual(pickle.loads(marker.token), (16000, 1)) | |
422 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
423 marker = self.FindMarkerByNumber(response.new_progress_marker, autofill) | |
424 self.assertEqual(pickle.loads(marker.token), (16000, 1)) | |
425 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
426 | |
427 msg = sync_pb2.GetUpdatesMessage() | |
428 marker = msg.from_progress_marker.add() | |
429 marker.data_type_id = autofill.number | |
430 marker.timestamp_token_for_migration = 3000 | |
431 marker = msg.from_progress_marker.add() | |
432 marker.data_type_id = theme.number | |
433 marker.timestamp_token_for_migration = 3000 | |
434 sieve = chromiumsync.UpdateSieve(msg) | |
435 self.assertEqual(sieve._state, | |
436 {chromiumsync.TOP_LEVEL: 3000, | |
437 chromiumsync.AUTOFILL: 3000, | |
438 chromiumsync.THEME: 3000}) | |
439 response = sync_pb2.GetUpdatesResponse() | |
440 sieve.SaveProgress(3000, response) # Already up to date | |
441 self.assertEqual(2, len(response.new_progress_marker)) | |
442 self.assertFalse(response.HasField('new_timestamp')) | |
443 marker = self.FindMarkerByNumber(response.new_progress_marker, theme) | |
444 self.assertEqual(pickle.loads(marker.token), (3000, 1)) | |
445 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
446 marker = self.FindMarkerByNumber(response.new_progress_marker, autofill) | |
447 self.assertEqual(pickle.loads(marker.token), (3000, 1)) | |
448 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
449 | |
450 def testCheckRaiseTransientError(self): | |
451 testserver = chromiumsync.TestServer() | |
452 http_code, raw_respon = testserver.HandleSetTransientError() | |
453 self.assertEqual(http_code, 200) | |
454 try: | |
455 testserver.CheckTransientError() | |
456 self.fail('Should have raised transient error exception') | |
457 except chromiumsync.TransientError: | |
458 self.assertTrue(testserver.transient_error) | |
459 | |
460 def testUpdateSieveStoreMigration(self): | |
461 autofill = chromiumsync.SYNC_TYPE_FIELDS['autofill'] | |
462 theme = chromiumsync.SYNC_TYPE_FIELDS['theme'] | |
463 migrator = chromiumsync.MigrationHistory() | |
464 msg = sync_pb2.GetUpdatesMessage() | |
465 marker = msg.from_progress_marker.add() | |
466 marker.data_type_id = autofill.number | |
467 marker.token = pickle.dumps((15412, 1)) | |
468 marker = msg.from_progress_marker.add() | |
469 marker.data_type_id = theme.number | |
470 marker.token = pickle.dumps((15413, 1)) | |
471 sieve = chromiumsync.UpdateSieve(msg, migrator) | |
472 sieve.CheckMigrationState() | |
473 | |
474 migrator.Bump([chromiumsync.BOOKMARK, chromiumsync.PASSWORD]) # v=2 | |
475 sieve = chromiumsync.UpdateSieve(msg, migrator) | |
476 sieve.CheckMigrationState() | |
477 self.assertEqual(sieve._state, | |
478 {chromiumsync.TOP_LEVEL: 15412, | |
479 chromiumsync.AUTOFILL: 15412, | |
480 chromiumsync.THEME: 15413}) | |
481 | |
482 migrator.Bump([chromiumsync.AUTOFILL, chromiumsync.PASSWORD]) # v=3 | |
483 sieve = chromiumsync.UpdateSieve(msg, migrator) | |
484 try: | |
485 sieve.CheckMigrationState() | |
486 self.fail('Should have raised.') | |
487 except chromiumsync.MigrationDoneError, error: | |
488 # We want this to happen. | |
489 self.assertEqual([chromiumsync.AUTOFILL], error.datatypes) | |
490 | |
491 msg = sync_pb2.GetUpdatesMessage() | |
492 marker = msg.from_progress_marker.add() | |
493 marker.data_type_id = autofill.number | |
494 marker.token = '' | |
495 marker = msg.from_progress_marker.add() | |
496 marker.data_type_id = theme.number | |
497 marker.token = pickle.dumps((15413, 1)) | |
498 sieve = chromiumsync.UpdateSieve(msg, migrator) | |
499 sieve.CheckMigrationState() | |
500 response = sync_pb2.GetUpdatesResponse() | |
501 sieve.SaveProgress(15412, response) # There were updates | |
502 self.assertEqual(1, len(response.new_progress_marker)) | |
503 self.assertFalse(response.HasField('new_timestamp')) | |
504 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
505 marker = self.FindMarkerByNumber(response.new_progress_marker, autofill) | |
506 self.assertEqual(pickle.loads(marker.token), (15412, 3)) | |
507 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
508 msg = sync_pb2.GetUpdatesMessage() | |
509 marker = msg.from_progress_marker.add() | |
510 marker.data_type_id = autofill.number | |
511 marker.token = pickle.dumps((15412, 3)) | |
512 marker = msg.from_progress_marker.add() | |
513 marker.data_type_id = theme.number | |
514 marker.token = pickle.dumps((15413, 1)) | |
515 sieve = chromiumsync.UpdateSieve(msg, migrator) | |
516 sieve.CheckMigrationState() | |
517 | |
518 migrator.Bump([chromiumsync.THEME, chromiumsync.AUTOFILL]) # v=4 | |
519 migrator.Bump([chromiumsync.AUTOFILL]) # v=5 | |
520 sieve = chromiumsync.UpdateSieve(msg, migrator) | |
521 try: | |
522 sieve.CheckMigrationState() | |
523 self.fail("Should have raised.") | |
524 except chromiumsync.MigrationDoneError, error: | |
525 # We want this to happen. | |
526 self.assertEqual(set([chromiumsync.THEME, chromiumsync.AUTOFILL]), | |
527 set(error.datatypes)) | |
528 msg = sync_pb2.GetUpdatesMessage() | |
529 marker = msg.from_progress_marker.add() | |
530 marker.data_type_id = autofill.number | |
531 marker.token = '' | |
532 marker = msg.from_progress_marker.add() | |
533 marker.data_type_id = theme.number | |
534 marker.token = pickle.dumps((15413, 1)) | |
535 sieve = chromiumsync.UpdateSieve(msg, migrator) | |
536 try: | |
537 sieve.CheckMigrationState() | |
538 self.fail("Should have raised.") | |
539 except chromiumsync.MigrationDoneError, error: | |
540 # We want this to happen. | |
541 self.assertEqual([chromiumsync.THEME], error.datatypes) | |
542 | |
543 msg = sync_pb2.GetUpdatesMessage() | |
544 marker = msg.from_progress_marker.add() | |
545 marker.data_type_id = autofill.number | |
546 marker.token = '' | |
547 marker = msg.from_progress_marker.add() | |
548 marker.data_type_id = theme.number | |
549 marker.token = '' | |
550 sieve = chromiumsync.UpdateSieve(msg, migrator) | |
551 sieve.CheckMigrationState() | |
552 response = sync_pb2.GetUpdatesResponse() | |
553 sieve.SaveProgress(15412, response) # There were updates | |
554 self.assertEqual(2, len(response.new_progress_marker)) | |
555 self.assertFalse(response.HasField('new_timestamp')) | |
556 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
557 marker = self.FindMarkerByNumber(response.new_progress_marker, autofill) | |
558 self.assertEqual(pickle.loads(marker.token), (15412, 5)) | |
559 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
560 marker = self.FindMarkerByNumber(response.new_progress_marker, theme) | |
561 self.assertEqual(pickle.loads(marker.token), (15412, 4)) | |
562 self.assertFalse(marker.HasField('timestamp_token_for_migration')) | |
563 msg = sync_pb2.GetUpdatesMessage() | |
564 marker = msg.from_progress_marker.add() | |
565 marker.data_type_id = autofill.number | |
566 marker.token = pickle.dumps((15412, 5)) | |
567 marker = msg.from_progress_marker.add() | |
568 marker.data_type_id = theme.number | |
569 marker.token = pickle.dumps((15413, 4)) | |
570 sieve = chromiumsync.UpdateSieve(msg, migrator) | |
571 sieve.CheckMigrationState() | |
572 | |
573 def testCreateSyncedBookmarks(self): | |
574 version1, changes, remaining = ( | |
575 self.GetChangesFromTimestamp([chromiumsync.BOOKMARK], 0)) | |
576 id_string = self.model._MakeCurrentId(chromiumsync.BOOKMARK, | |
577 '<server tag>synced_bookmarks') | |
578 self.assertFalse(self.model._ItemExists(id_string)) | |
579 self._expect_synced_bookmarks_folder = True | |
580 self.model.TriggerCreateSyncedBookmarks() | |
581 self.assertTrue(self.model._ItemExists(id_string)) | |
582 | |
583 # Check that the version changed when the folder was created and the only | |
584 # change was the folder creation. | |
585 version2, changes, remaining = ( | |
586 self.GetChangesFromTimestamp([chromiumsync.BOOKMARK], version1)) | |
587 self.assertEqual(len(changes), 1) | |
588 self.assertEqual(changes[0].id_string, id_string) | |
589 self.assertNotEqual(version1, version2) | |
590 self.assertEqual( | |
591 self.ExpectedPermanentItemCount(chromiumsync.BOOKMARK), | |
592 version2) | |
593 | |
594 # Ensure getting from timestamp 0 includes the folder. | |
595 version, changes, remaining = ( | |
596 self.GetChangesFromTimestamp([chromiumsync.BOOKMARK], 0)) | |
597 self.assertEqual( | |
598 self.ExpectedPermanentItemCount(chromiumsync.BOOKMARK), | |
599 len(changes)) | |
600 self.assertEqual(version2, version) | |
601 | |
602 def testAcknowledgeManagedUser(self): | |
603 # Create permanent items. | |
604 self.GetChangesFromTimestamp([chromiumsync.MANAGED_USER], 0) | |
605 proto = sync_pb2.SyncEntity() | |
606 proto.id_string = 'abcd' | |
607 proto.version = 0 | |
608 | |
609 # Make sure the managed_user field exists. | |
610 proto.specifics.managed_user.acknowledged = False | |
611 self.assertTrue(proto.specifics.HasField('managed_user')) | |
612 self.AddToModel(proto) | |
613 version1, changes1, remaining1 = ( | |
614 self.GetChangesFromTimestamp([chromiumsync.MANAGED_USER], 0)) | |
615 for change in changes1: | |
616 self.assertTrue(not change.specifics.managed_user.acknowledged) | |
617 | |
618 # Turn on managed user acknowledgement | |
619 self.model.acknowledge_managed_users = True | |
620 | |
621 version2, changes2, remaining2 = ( | |
622 self.GetChangesFromTimestamp([chromiumsync.MANAGED_USER], 0)) | |
623 for change in changes2: | |
624 self.assertTrue(change.specifics.managed_user.acknowledged) | |
625 | |
626 def testGetKey(self): | |
627 [key1] = self.model.GetKeystoreKeys() | |
628 [key2] = self.model.GetKeystoreKeys() | |
629 self.assertTrue(len(key1)) | |
630 self.assertEqual(key1, key2) | |
631 | |
632 # Trigger the rotation. A subsequent GetUpdates should return the nigori | |
633 # node (whose timestamp was bumped by the rotation). | |
634 version1, changes, remaining = ( | |
635 self.GetChangesFromTimestamp([chromiumsync.NIGORI], 0)) | |
636 self.model.TriggerRotateKeystoreKeys() | |
637 version2, changes, remaining = ( | |
638 self.GetChangesFromTimestamp([chromiumsync.NIGORI], version1)) | |
639 self.assertNotEqual(version1, version2) | |
640 self.assertEquals(len(changes), 1) | |
641 self.assertEquals(changes[0].name, "Nigori") | |
642 | |
643 # The current keys should contain the old keys, with the new key appended. | |
644 [key1, key3] = self.model.GetKeystoreKeys() | |
645 self.assertEquals(key1, key2) | |
646 self.assertNotEqual(key1, key3) | |
647 self.assertTrue(len(key3) > 0) | |
648 | |
649 def testTriggerEnableKeystoreEncryption(self): | |
650 version1, changes, remaining = ( | |
651 self.GetChangesFromTimestamp([chromiumsync.EXPERIMENTS], 0)) | |
652 keystore_encryption_id_string = ( | |
653 self.model._ClientTagToId( | |
654 chromiumsync.EXPERIMENTS, | |
655 chromiumsync.KEYSTORE_ENCRYPTION_EXPERIMENT_TAG)) | |
656 | |
657 self.assertFalse(self.model._ItemExists(keystore_encryption_id_string)) | |
658 self.model.TriggerEnableKeystoreEncryption() | |
659 self.assertTrue(self.model._ItemExists(keystore_encryption_id_string)) | |
660 | |
661 # The creation of the experiment should be downloaded on the next | |
662 # GetUpdates. | |
663 version2, changes, remaining = ( | |
664 self.GetChangesFromTimestamp([chromiumsync.EXPERIMENTS], version1)) | |
665 self.assertEqual(len(changes), 1) | |
666 self.assertEqual(changes[0].id_string, keystore_encryption_id_string) | |
667 self.assertNotEqual(version1, version2) | |
668 | |
669 # Verify the experiment was created properly and is enabled. | |
670 self.assertEqual(chromiumsync.KEYSTORE_ENCRYPTION_EXPERIMENT_TAG, | |
671 changes[0].client_defined_unique_tag) | |
672 self.assertTrue(changes[0].HasField("specifics")) | |
673 self.assertTrue(changes[0].specifics.HasField("experiments")) | |
674 self.assertTrue( | |
675 changes[0].specifics.experiments.HasField("keystore_encryption")) | |
676 self.assertTrue( | |
677 changes[0].specifics.experiments.keystore_encryption.enabled) | |
678 | |
679 if __name__ == '__main__': | |
680 unittest.main() | |
OLD | NEW |