1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#!/usr/bin/python2.4
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# Copyright (c) 2010 The Chromium Authors. All rights reserved.
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# Use of this source code is governed by a BSD-style license that can be
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# found in the LICENSE file.
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch"""Tests exercising chromiumsync and SyncDataModel."""
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochimport unittest
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickimport autofill_specifics_pb2
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochimport chromiumsync
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochimport sync_pb2
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickimport theme_specifics_pb2
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SyncDataModelTest(unittest.TestCase):
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def setUp(self):
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.model = chromiumsync.SyncDataModel()
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def AddToModel(self, proto):
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.model._entries[proto.id_string] = proto
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  def GetChangesFromTimestamp(self, requested_types, timestamp):
23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    message = sync_pb2.GetUpdatesMessage()
24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    message.from_timestamp = timestamp
25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    for data_type in requested_types:
26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      message.requested_types.Extensions[
27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        chromiumsync.SYNC_TYPE_TO_EXTENSION[data_type]].SetInParent()
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return self.model.GetChanges(chromiumsync.UpdateSieve(message))
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def testPermanentItemSpecs(self):
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    specs = chromiumsync.SyncDataModel._PERMANENT_ITEM_SPECS
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    declared_specs = set(['0'])
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    for spec in specs:
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertTrue(spec.parent_tag in declared_specs, 'parent tags must '
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      'be declared before use')
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      declared_specs.add(spec.tag)
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    unique_datatypes = set([x.sync_type for x in specs])
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    self.assertEqual(unique_datatypes, set(chromiumsync.ALL_TYPES),
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                     'Every sync datatype should have a permanent folder '
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                     'associated with it')
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def testSaveEntry(self):
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    proto = sync_pb2.SyncEntity()
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    proto.id_string = 'abcd'
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    proto.version = 0
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.assertFalse(self.model._ItemExists(proto.id_string))
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.model._SaveEntry(proto)
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.assertEqual(1, proto.version)
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.assertTrue(self.model._ItemExists(proto.id_string))
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.model._SaveEntry(proto)
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.assertEqual(2, proto.version)
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    proto.version = 0
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.assertTrue(self.model._ItemExists(proto.id_string))
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.assertEqual(2, self.model._entries[proto.id_string].version)
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def testWritePosition(self):
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    def MakeProto(id_string, parent, position):
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      proto = sync_pb2.SyncEntity()
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      proto.id_string = id_string
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      proto.position_in_parent = position
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      proto.parent_id_string = parent
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.AddToModel(proto)
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MakeProto('a', 'X', 1000)
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MakeProto('b', 'X', 1800)
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MakeProto('c', 'X', 2600)
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MakeProto('a1', 'Z', 1007)
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MakeProto('a2', 'Z', 1807)
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MakeProto('a3', 'Z', 2607)
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MakeProto('s', 'Y', 10000)
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    def AssertPositionResult(my_id, parent_id, prev_id, expected_position):
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      entry = sync_pb2.SyncEntity()
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      entry.id_string = my_id
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.model._WritePosition(entry, parent_id, prev_id)
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(expected_position, entry.position_in_parent)
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(parent_id, entry.parent_id_string)
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertFalse(entry.HasField('insert_after_item_id'))
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('new', 'new_parent', '', 0)
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('new', 'Y', '', 10000 - (2 ** 20))
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('new', 'Y', 's', 10000 + (2 ** 20))
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('s', 'Y', '', 10000)
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('s', 'Y', 's', 10000)
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('a1', 'Z', '', 1007)
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('new', 'X', '', 1000 - (2 ** 20))
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('new', 'X', 'a', 1100)
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('new', 'X', 'b', 1900)
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('new', 'X', 'c', 2600 + (2 ** 20))
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('a1', 'X', '', 1000 - (2 ** 20))
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('a1', 'X', 'a', 1100)
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('a1', 'X', 'b', 1900)
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('a1', 'X', 'c', 2600 + (2 ** 20))
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('a', 'X', '', 1000)
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('a', 'X', 'b', 1900)
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('a', 'X', 'c', 2600 + (2 ** 20))
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('b', 'X', '', 1000 - (2 ** 20))
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('b', 'X', 'a', 1800)
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('b', 'X', 'c', 2600 + (2 ** 20))
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('c', 'X', '', 1000 - (2 ** 20))
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('c', 'X', 'a', 1100)
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AssertPositionResult('c', 'X', 'b', 2600)
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def testCreatePermanentItems(self):
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.model._CreatePermanentItems(chromiumsync.ALL_TYPES)
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    self.assertEqual(len(chromiumsync.ALL_TYPES) + 2,
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     len(self.model._entries))
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def ExpectedPermanentItemCount(self, sync_type):
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if sync_type == chromiumsync.BOOKMARK:
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return 4
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    elif sync_type == chromiumsync.TOP_LEVEL:
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return 1
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else:
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return 2
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def testGetChangesFromTimestampZeroForEachType(self):
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    all_types = chromiumsync.ALL_TYPES[1:]
126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    for sync_type in all_types:
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.model = chromiumsync.SyncDataModel()
128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      request_types = [sync_type]
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, remaining = (
131731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, 0))
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      expected_count = self.ExpectedPermanentItemCount(sync_type)
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(expected_count, version)
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(expected_count, len(changes))
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual('google_chrome', changes[0].server_defined_unique_tag)
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for change in changes:
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(change.HasField('server_defined_unique_tag'))
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertEqual(change.version, change.sync_timestamp)
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(change.version <= version)
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # Test idempotence: another GetUpdates from ts=0 shouldn't recreate.
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, remaining = (
144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, 0))
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(expected_count, version)
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(expected_count, len(changes))
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(0, remaining)
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # Doing a wider GetUpdates from timestamp zero shouldn't recreate either.
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new_version, changes, remaining = (
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(all_types, 0))
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(len(chromiumsync.SyncDataModel._PERMANENT_ITEM_SPECS),
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       new_version)
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(new_version, len(changes))
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(0, remaining)
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, remaining = (
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, 0))
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(new_version, version)
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(expected_count, len(changes))
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(0, remaining)
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def testBatchSize(self):
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for sync_type in chromiumsync.ALL_TYPES[1:]:
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      specifics = chromiumsync.GetDefaultEntitySpecifics(sync_type)
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.model = chromiumsync.SyncDataModel()
166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      request_types = [sync_type]
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for i in range(self.model._BATCH_SIZE*3):
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        entry = sync_pb2.SyncEntity()
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        entry.id_string = 'batch test %d' % i
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        entry.specifics.CopyFrom(specifics)
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.model._SaveEntry(entry)
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      last_bit = self.ExpectedPermanentItemCount(sync_type)
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, changes_remaining = (
175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, 0))
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(self.model._BATCH_SIZE, version)
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(self.model._BATCH_SIZE*2 + last_bit, changes_remaining)
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, changes_remaining = (
179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, version))
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(self.model._BATCH_SIZE*2, version)
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(self.model._BATCH_SIZE + last_bit, changes_remaining)
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, changes_remaining = (
183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, version))
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(self.model._BATCH_SIZE*3, version)
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(last_bit, changes_remaining)
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, changes_remaining = (
187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, version))
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(self.model._BATCH_SIZE*3 + last_bit, version)
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(0, changes_remaining)
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # Now delete a third of the items.
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for i in xrange(self.model._BATCH_SIZE*3 - 1, 0, -3):
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        entry = sync_pb2.SyncEntity()
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        entry.id_string = 'batch test %d' % i
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        entry.deleted = True
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.model._SaveEntry(entry)
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # The batch counts shouldn't change.
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, changes_remaining = (
200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, 0))
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(self.model._BATCH_SIZE, len(changes))
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(self.model._BATCH_SIZE*2 + last_bit, changes_remaining)
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, changes_remaining = (
204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, version))
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(self.model._BATCH_SIZE, len(changes))
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(self.model._BATCH_SIZE + last_bit, changes_remaining)
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, changes_remaining = (
208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, version))
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(self.model._BATCH_SIZE, len(changes))
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(last_bit, changes_remaining)
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, changes_remaining = (
212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp(request_types, version))
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(last_bit, len(changes))
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(self.model._BATCH_SIZE*4 + last_bit, version)
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(0, changes_remaining)
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  def testCommitEachDataType(self):
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for sync_type in chromiumsync.ALL_TYPES[1:]:
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      specifics = chromiumsync.GetDefaultEntitySpecifics(sync_type)
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.model = chromiumsync.SyncDataModel()
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      my_cache_guid = '112358132134'
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      parent = 'foobar'
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      commit_session = {}
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # Start with a GetUpdates from timestamp 0, to populate permanent items.
2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      original_version, original_changes, changes_remaining = (
227731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp([sync_type], 0))
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      def DoCommit(original=None, id_string='', name=None, parent=None,
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                   prev=None):
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        proto = sync_pb2.SyncEntity()
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if original is not None:
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          proto.version = original.version
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          proto.id_string = original.id_string
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          proto.parent_id_string = original.parent_id_string
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          proto.name = original.name
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        else:
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          proto.id_string = id_string
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          proto.version = 0
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        proto.specifics.CopyFrom(specifics)
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if name is not None:
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          proto.name = name
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if parent:
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          proto.parent_id_string = parent.id_string
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if prev:
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          proto.insert_after_item_id = prev.id_string
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        else:
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          proto.insert_after_item_id = ''
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        proto.folder = True
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        proto.deleted = False
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        result = self.model.CommitEntry(proto, my_cache_guid, commit_session)
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(result)
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return (proto, result)
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # Commit a new item.
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      proto1, result1 = DoCommit(name='namae', id_string='Foo',
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 parent=original_changes[-1])
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # Commit an item whose parent is another item (referenced via the
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # pre-commit ID).
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      proto2, result2 = DoCommit(name='Secondo', id_string='Bar',
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 parent=proto1)
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        # Commit a sibling of the second item.
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      proto3, result3 = DoCommit(name='Third!', id_string='Baz',
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 parent=proto1, prev=proto2)
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(3, len(commit_session))
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for p, r in [(proto1, result1), (proto2, result2), (proto3, result3)]:
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertNotEqual(r.id_string, p.id_string)
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertEqual(r.originator_client_item_id, p.id_string)
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertEqual(r.originator_cache_guid, my_cache_guid)
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(r is not self.model._entries[r.id_string],
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        "Commit result didn't make a defensive copy.")
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(p is not self.model._entries[r.id_string],
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        "Commit result didn't make a defensive copy.")
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertEqual(commit_session.get(p.id_string), r.id_string)
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(r.version > original_version)
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(result1.parent_id_string, proto1.parent_id_string)
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(result2.parent_id_string, result1.id_string)
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, remaining = (
280731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp([sync_type], original_version))
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(3, len(changes))
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(0, remaining)
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(original_version + 3, version)
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual([result1, result2, result3], changes)
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for c in changes:
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(c is not self.model._entries[c.id_string],
2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        "GetChanges didn't make a defensive copy.")
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertTrue(result2.position_in_parent < result3.position_in_parent)
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(0, result2.position_in_parent)
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # Now update the items so that the second item is the parent of the
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # first; with the first sandwiched between two new items (4 and 5).
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # Do this in a new commit session, meaning we'll reference items from
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      # the first batch by their post-commit, server IDs.
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      commit_session = {}
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      old_cache_guid = my_cache_guid
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      my_cache_guid = 'A different GUID'
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      proto2b, result2b = DoCommit(original=result2,
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   parent=original_changes[-1])
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      proto4, result4 = DoCommit(id_string='ID4', name='Four',
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 parent=result2, prev=None)
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      proto1b, result1b = DoCommit(original=result1,
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   parent=result2, prev=proto4)
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      proto5, result5 = DoCommit(id_string='ID5', name='Five', parent=result2,
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 prev=result1)
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(2, len(commit_session), 'Only new items in second '
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       'batch should be in the session')
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for p, r, original in [(proto2b, result2b, proto2),
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             (proto4, result4, proto4),
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             (proto1b, result1b, proto1),
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             (proto5, result5, proto5)]:
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertEqual(r.originator_client_item_id, original.id_string)
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if original is not p:
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          self.assertEqual(r.id_string, p.id_string,
3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           'Ids should be stable after first commit')
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          self.assertEqual(r.originator_cache_guid, old_cache_guid)
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        else:
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          self.assertNotEqual(r.id_string, p.id_string)
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          self.assertEqual(r.originator_cache_guid, my_cache_guid)
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          self.assertEqual(commit_session.get(p.id_string), r.id_string)
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(r is not self.model._entries[r.id_string],
3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        "Commit result didn't make a defensive copy.")
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(p is not self.model._entries[r.id_string],
3253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        "Commit didn't make a defensive copy.")
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(r.version > p.version)
3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      version, changes, remaining = (
328731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          self.GetChangesFromTimestamp([sync_type], original_version))
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(5, len(changes))
3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      self.assertEqual(0, remaining)
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual(original_version + 7, version)
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertEqual([result3, result2b, result4, result1b, result5], changes)
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for c in changes:
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        self.assertTrue(c is not self.model._entries[c.id_string],
3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        "GetChanges didn't make a defensive copy.")
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertTrue(result4.parent_id_string ==
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      result1b.parent_id_string ==
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      result5.parent_id_string ==
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      result2b.id_string)
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      self.assertTrue(result4.position_in_parent <
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      result1b.position_in_parent <
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      result5.position_in_parent)
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
344731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  def testUpdateSieve(self):
345731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    # from_timestamp, legacy mode
346731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    autofill = autofill_specifics_pb2.autofill
347731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    theme = theme_specifics_pb2.theme
348731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    msg = sync_pb2.GetUpdatesMessage()
349731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    msg.from_timestamp = 15412
350731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    msg.requested_types.Extensions[autofill].SetInParent()
351731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    msg.requested_types.Extensions[theme].SetInParent()
352731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
353731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve = chromiumsync.UpdateSieve(msg)
354731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(sieve._state,
355731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        {chromiumsync.TOP_LEVEL: 15412,
356731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.AUTOFILL: 15412,
357731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.THEME: 15412})
358731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
359731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    response = sync_pb2.GetUpdatesResponse()
360731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve.SaveProgress(15412, response)
361731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(0, len(response.new_progress_marker))
362731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(response.HasField('new_timestamp'))
363731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
364731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    response = sync_pb2.GetUpdatesResponse()
365731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve.SaveProgress(15413, response)
366731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(0, len(response.new_progress_marker))
367731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertTrue(response.HasField('new_timestamp'))
368731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(15413, response.new_timestamp)
369731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
370731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    # Existing tokens
371731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    msg = sync_pb2.GetUpdatesMessage()
372731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = msg.from_progress_marker.add()
373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.data_type_id = autofill.number
374731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.token = '15412'
375731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = msg.from_progress_marker.add()
376731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.data_type_id = theme.number
377731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.token = '15413'
378731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve = chromiumsync.UpdateSieve(msg)
379731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(sieve._state,
380731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        {chromiumsync.TOP_LEVEL: 15412,
381731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.AUTOFILL: 15412,
382731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.THEME: 15413})
383731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
384731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    response = sync_pb2.GetUpdatesResponse()
385731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve.SaveProgress(15413, response)
386731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(1, len(response.new_progress_marker))
387731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(response.HasField('new_timestamp'))
388731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = response.new_progress_marker[0]
389731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.data_type_id, autofill.number)
390731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.token, '15413')
391731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(marker.HasField('timestamp_token_for_migration'))
392731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
393731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    # Empty tokens indicating from timestamp = 0
394731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    msg = sync_pb2.GetUpdatesMessage()
395731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = msg.from_progress_marker.add()
396731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.data_type_id = autofill.number
397731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.token = '412'
398731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = msg.from_progress_marker.add()
399731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.data_type_id = theme.number
400731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.token = ''
401731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve = chromiumsync.UpdateSieve(msg)
402731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(sieve._state,
403731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        {chromiumsync.TOP_LEVEL: 0,
404731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.AUTOFILL: 412,
405731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.THEME: 0})
406731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    response = sync_pb2.GetUpdatesResponse()
407731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve.SaveProgress(1, response)
408731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(1, len(response.new_progress_marker))
409731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(response.HasField('new_timestamp'))
410731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = response.new_progress_marker[0]
411731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.data_type_id, theme.number)
412731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.token, '1')
413731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(marker.HasField('timestamp_token_for_migration'))
414731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
415731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    response = sync_pb2.GetUpdatesResponse()
416731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve.SaveProgress(412, response)
417731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(1, len(response.new_progress_marker))
418731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(response.HasField('new_timestamp'))
419731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = response.new_progress_marker[0]
420731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.data_type_id, theme.number)
421731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.token, '412')
422731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(marker.HasField('timestamp_token_for_migration'))
423731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
424731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    response = sync_pb2.GetUpdatesResponse()
425731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve.SaveProgress(413, response)
426731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(2, len(response.new_progress_marker))
427731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(response.HasField('new_timestamp'))
428731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = response.new_progress_marker[0]
429731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.data_type_id, theme.number)
430731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.token, '413')
431731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(marker.HasField('timestamp_token_for_migration'))
432731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = response.new_progress_marker[1]
433731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.data_type_id, autofill.number)
434731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.token, '413')
435731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(marker.HasField('timestamp_token_for_migration'))
436731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
437731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    # Migration token timestamps (client gives timestamp, server returns token)
438731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    msg = sync_pb2.GetUpdatesMessage()
439731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = msg.from_progress_marker.add()
440731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.data_type_id = autofill.number
441731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.timestamp_token_for_migration = 15213
442731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = msg.from_progress_marker.add()
443731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.data_type_id = theme.number
444731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.timestamp_token_for_migration = 15211
445731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve = chromiumsync.UpdateSieve(msg)
446731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(sieve._state,
447731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        {chromiumsync.TOP_LEVEL: 15211,
448731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.AUTOFILL: 15213,
449731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.THEME: 15211})
450731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    response = sync_pb2.GetUpdatesResponse()
451731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve.SaveProgress(16000, response)  # There were updates
452731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(2, len(response.new_progress_marker))
453731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(response.HasField('new_timestamp'))
454731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = response.new_progress_marker[0]
455731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.data_type_id, theme.number)
456731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.token, '16000')
457731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(marker.HasField('timestamp_token_for_migration'))
458731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = response.new_progress_marker[1]
459731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.data_type_id, autofill.number)
460731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.token, '16000')
461731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(marker.HasField('timestamp_token_for_migration'))
462731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
463731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    msg = sync_pb2.GetUpdatesMessage()
464731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = msg.from_progress_marker.add()
465731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.data_type_id = autofill.number
466731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.timestamp_token_for_migration = 3000
467731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = msg.from_progress_marker.add()
468731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.data_type_id = theme.number
469731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker.timestamp_token_for_migration = 3000
470731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve = chromiumsync.UpdateSieve(msg)
471731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(sieve._state,
472731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        {chromiumsync.TOP_LEVEL: 3000,
473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.AUTOFILL: 3000,
474731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick         chromiumsync.THEME: 3000})
475731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    response = sync_pb2.GetUpdatesResponse()
476731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    sieve.SaveProgress(3000, response)  # Already up to date
477731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(2, len(response.new_progress_marker))
478731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(response.HasField('new_timestamp'))
479731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = response.new_progress_marker[0]
480731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.data_type_id, theme.number)
481731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.token, '3000')
482731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(marker.HasField('timestamp_token_for_migration'))
483731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    marker = response.new_progress_marker[1]
484731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.data_type_id, autofill.number)
485731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertEqual(marker.token, '3000')
486731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    self.assertFalse(marker.HasField('timestamp_token_for_migration'))
487731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochif __name__ == '__main__':
4903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  unittest.main()
491