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."""
11 import autofill_specifics_pb2
12 import bookmark_specifics_pb2
14 import managed_user_specifics_pb2
16 import theme_specifics_pb2
18 class SyncDataModelTest(unittest
.TestCase
):
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
:
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'])
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 '
59 def testSaveEntry(self
):
60 proto
= sync_pb2
.SyncEntity()
61 proto
.id_string
= 'abcd'
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
)
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
:
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
),
119 len(chromiumsync
.SyncDataModel
._PERMANENT
_ITEM
_SPECS
) -1,
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
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'
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,
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
205 proto
.id_string
= id_string
207 proto
.specifics
.CopyFrom(specifics
)
211 proto
.parent_id_string
= parent
.id_string
212 proto
.insert_after_item_id
= 'please discard'
213 proto
.position_in_parent
= position
215 proto
.deleted
= False
216 result
= self
.model
.CommitEntry(proto
, my_cache_guid
, commit_session
)
217 self
.assertTrue(result
)
218 return (proto
, result
)
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
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
)
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.
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
,
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
)
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
)
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
==
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
)
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
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
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)
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
)
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
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
)
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
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
)
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
547 marker
= msg
.from_progress_marker
.add()
548 marker
.data_type_id
= theme
.number
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
)
591 self
.ExpectedPermanentItemCount(chromiumsync
.BOOKMARK
),
594 # Ensure getting from timestamp 0 includes the folder.
595 version
, changes
, remaining
= (
596 self
.GetChangesFromTimestamp([chromiumsync
.BOOKMARK
], 0))
598 self
.ExpectedPermanentItemCount(chromiumsync
.BOOKMARK
),
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'
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
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"))
675 changes
[0].specifics
.experiments
.HasField("keystore_encryption"))
677 changes
[0].specifics
.experiments
.keystore_encryption
.enabled
)
679 if __name__
== '__main__':