| 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 |