Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / sync / tools / testserver / chromiumsync_test.py
blobd83e4146c828f6f8e3601779419d992b0e8ca017
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.
6 """Tests exercising chromiumsync and SyncDataModel."""
8 import pickle
9 import unittest
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
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
24 def AddToModel(self, proto):
25 self.model._entries[proto.id_string] = proto
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))
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)
44 def testPermanentItemSpecs(self):
45 specs = chromiumsync.SyncDataModel._PERMANENT_ITEM_SPECS
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)
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')
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)
73 def testCreatePermanentItems(self):
74 self.model._CreateDefaultPermanentItems(chromiumsync.ALL_TYPES)
75 self.assertEqual(len(chromiumsync.ALL_TYPES) + 1,
76 len(self.model._entries))
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
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]
93 version, changes, remaining = (
94 self.GetChangesFromTimestamp(request_types, 0))
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)
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)
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)
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]
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)
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)
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)
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 = {}
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))
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)
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)
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)
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)
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)
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()
318 sieve = chromiumsync.UpdateSieve(msg)
319 self.assertEqual(sieve._state,
320 {chromiumsync.TOP_LEVEL: 15412,
321 chromiumsync.AUTOFILL: 15412,
322 chromiumsync.THEME: 15412})
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'))
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)
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})
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'))
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'))
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'))
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'))
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'))
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'))
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)
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()
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})
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)
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()
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)
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()
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))
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)
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)
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
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)
618 # Turn on managed user acknowledgement
619 self.model.acknowledge_managed_users = True
621 version2, changes2, remaining2 = (
622 self.GetChangesFromTimestamp([chromiumsync.MANAGED_USER], 0))
623 for change in changes2:
624 self.assertTrue(change.specifics.managed_user.acknowledged)
626 def testGetKey(self):
627 [key1] = self.model.GetKeystoreKeys()
628 [key2] = self.model.GetKeystoreKeys()
629 self.assertTrue(len(key1))
630 self.assertEqual(key1, key2)
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")
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)
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))
657 self.assertFalse(self.model._ItemExists(keystore_encryption_id_string))
658 self.model.TriggerEnableKeystoreEncryption()
659 self.assertTrue(self.model._ItemExists(keystore_encryption_id_string))
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)
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)
679 if __name__ == '__main__':
680 unittest.main()