Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: sync/engine/apply_control_data_updates_unittest.cc

Issue 10832286: sync: Introduce control data types (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix unit tests Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/format_macros.h"
6 #include "base/location.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/stringprintf.h"
9 #include "sync/engine/apply_control_data_updates.h"
10 #include "sync/engine/syncer.h"
11 #include "sync/engine/syncer_util.h"
12 #include "sync/internal_api/public/test/test_entry_factory.h"
13 #include "sync/protocol/nigori_specifics.pb.h"
14 #include "sync/syncable/mutable_entry.h"
15 #include "sync/syncable/nigori_util.h"
16 #include "sync/syncable/read_transaction.h"
17 #include "sync/syncable/syncable_util.h"
18 #include "sync/syncable/write_transaction.h"
19 #include "sync/test/engine/fake_model_worker.h"
20 #include "sync/test/engine/syncer_command_test.h"
21 #include "sync/test/engine/test_id_factory.h"
22 #include "sync/util/cryptographer.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 namespace syncer {
26
27 using syncable::MutableEntry;
28 using syncable::UNITTEST;
29 using syncable::Id;
30
31 class ApplyControlDataUpdatesTest : public SyncerCommandTest {
32 public:
33 protected:
34 ApplyControlDataUpdatesTest() {}
35 virtual ~ApplyControlDataUpdatesTest() {}
36
37 virtual void SetUp() {
38 workers()->clear();
39 mutable_routing_info()->clear();
40 workers()->push_back(make_scoped_refptr(new FakeModelWorker(GROUP_UI)));
41 workers()->push_back(
42 make_scoped_refptr(new FakeModelWorker(GROUP_PASSWORD)));
43 (*mutable_routing_info())[BOOKMARKS] = GROUP_UI;
44 (*mutable_routing_info())[PASSWORDS] = GROUP_PASSWORD;
45 (*mutable_routing_info())[NIGORI] = GROUP_CONTROL;
46 SyncerCommandTest::SetUp();
47 entry_factory_.reset(new TestEntryFactory(directory()));
48 }
49
50 FakeEncryptor encryptor_;
51 TestIdFactory id_factory_;
52 scoped_ptr<TestEntryFactory> entry_factory_;
53 private:
54 DISALLOW_COPY_AND_ASSIGN(ApplyControlDataUpdatesTest);
55 };
56
57 TEST_F(ApplyControlDataUpdatesTest, NigoriUpdate) {
58 // Storing the cryptographer separately is bad, but for this test we
59 // know it's safe.
60 Cryptographer* cryptographer;
61 ModelTypeSet encrypted_types;
62 encrypted_types.Put(PASSWORDS);
63 encrypted_types.Put(NIGORI);
64 {
65 syncable::ReadTransaction trans(FROM_HERE, directory());
66 cryptographer = directory()->GetCryptographer(&trans);
67 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types));
68 }
69
70 // Nigori node updates should update the Cryptographer.
71 Cryptographer other_cryptographer(&encryptor_);
72 KeyParams params = {"localhost", "dummy", "foobar"};
73 other_cryptographer.AddKey(params);
74
75 sync_pb::EntitySpecifics specifics;
76 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
77 other_cryptographer.GetKeys(nigori->mutable_encrypted());
78 nigori->set_encrypt_bookmarks(true);
79 encrypted_types.Put(BOOKMARKS);
80 entry_factory_->CreateUnappliedNewItem(
81 ModelTypeToRootTag(NIGORI), specifics, true);
82 EXPECT_FALSE(cryptographer->has_pending_keys());
83
84 ApplyControlDataUpdates(directory());
85
86 EXPECT_FALSE(cryptographer->is_ready());
87 EXPECT_TRUE(cryptographer->has_pending_keys());
88 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(ModelTypeSet::All()));
89 }
90
91 TEST_F(ApplyControlDataUpdatesTest, NigoriUpdateForDisabledTypes) {
92 // Storing the cryptographer separately is bad, but for this test we
93 // know it's safe.
94 Cryptographer* cryptographer;
95 ModelTypeSet encrypted_types;
96 encrypted_types.Put(PASSWORDS);
97 encrypted_types.Put(NIGORI);
98 {
99 syncable::ReadTransaction trans(FROM_HERE, directory());
100 cryptographer = directory()->GetCryptographer(&trans);
101 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types));
102 }
103
104 // Nigori node updates should update the Cryptographer.
105 Cryptographer other_cryptographer(&encryptor_);
106 KeyParams params = {"localhost", "dummy", "foobar"};
107 other_cryptographer.AddKey(params);
108
109 sync_pb::EntitySpecifics specifics;
110 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
111 other_cryptographer.GetKeys(nigori->mutable_encrypted());
112 nigori->set_encrypt_sessions(true);
113 nigori->set_encrypt_themes(true);
114 encrypted_types.Put(SESSIONS);
115 encrypted_types.Put(THEMES);
116 entry_factory_->CreateUnappliedNewItem(
117 ModelTypeToRootTag(NIGORI), specifics, true);
118 EXPECT_FALSE(cryptographer->has_pending_keys());
119
120 ApplyControlDataUpdates(directory());
121
122 EXPECT_FALSE(cryptographer->is_ready());
123 EXPECT_TRUE(cryptographer->has_pending_keys());
124 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(ModelTypeSet::All()));
Nicolas Zea 2012/08/16 20:55:02 check nigori's initial sync ended for each of thes
rlarocque 2012/08/17 19:47:18 These are supposed to test changes that occur in s
Nicolas Zea 2012/08/20 20:44:28 NigoriUpdate above seems to just test the applicat
rlarocque 2012/08/22 23:46:24 Good point. I forgot that ApplyControlDataUpdates
125 }
126
127 // Create some local unsynced and unencrypted data. Apply a nigori update that
128 // turns on encryption for the unsynced data. Ensure we properly encrypt the
129 // data as part of the nigori update. Apply another nigori update with no
130 // changes. Ensure we ignore already-encrypted unsynced data and that nothing
131 // breaks.
132 TEST_F(ApplyControlDataUpdatesTest, EncryptUnsyncedChanges) {
133 // Storing the cryptographer separately is bad, but for this test we
134 // know it's safe.
135 Cryptographer* cryptographer;
136 ModelTypeSet encrypted_types;
137 encrypted_types.Put(PASSWORDS);
138 encrypted_types.Put(NIGORI);
139 {
140 syncable::ReadTransaction trans(FROM_HERE, directory());
141 cryptographer = directory()->GetCryptographer(&trans);
142 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types));
143
144 // With default encrypted_types, this should be true.
145 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
146
147 Syncer::UnsyncedMetaHandles handles;
148 GetUnsyncedEntries(&trans, &handles);
149 EXPECT_TRUE(handles.empty());
150 }
151
152 // Create unsynced bookmarks without encryption.
153 // First item is a folder
154 Id folder_id = id_factory_.NewLocalId();
155 entry_factory_->CreateUnsyncedItem(folder_id, id_factory_.root(), "folder",
156 true, BOOKMARKS, NULL);
157 // Next five items are children of the folder
158 size_t i;
159 size_t batch_s = 5;
160 for (i = 0; i < batch_s; ++i) {
161 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
162 base::StringPrintf("Item %"PRIuS"", i),
163 false, BOOKMARKS, NULL);
164 }
165 // Next five items are children of the root.
166 for (; i < 2*batch_s; ++i) {
167 entry_factory_->CreateUnsyncedItem(
168 id_factory_.NewLocalId(), id_factory_.root(),
169 base::StringPrintf("Item %"PRIuS"", i), false,
170 BOOKMARKS, NULL);
171 }
172
173 KeyParams params = {"localhost", "dummy", "foobar"};
174 cryptographer->AddKey(params);
175 sync_pb::EntitySpecifics specifics;
176 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
177 cryptographer->GetKeys(nigori->mutable_encrypted());
178 nigori->set_encrypt_bookmarks(true);
179 encrypted_types.Put(BOOKMARKS);
180 entry_factory_->CreateUnappliedNewItem(
181 ModelTypeToRootTag(NIGORI), specifics, true);
182 EXPECT_FALSE(cryptographer->has_pending_keys());
183 EXPECT_TRUE(cryptographer->is_ready());
184
185 {
186 // Ensure we have unsynced nodes that aren't properly encrypted.
187 syncable::ReadTransaction trans(FROM_HERE, directory());
188 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
189
190 Syncer::UnsyncedMetaHandles handles;
191 GetUnsyncedEntries(&trans, &handles);
192 EXPECT_EQ(2*batch_s+1, handles.size());
193 }
194
195 ApplyControlDataUpdates(directory());
196
197 EXPECT_FALSE(cryptographer->has_pending_keys());
198 EXPECT_TRUE(cryptographer->is_ready());
199 {
200 syncable::ReadTransaction trans(FROM_HERE, directory());
201
202 // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes
203 // should be encrypted now.
204 EXPECT_TRUE(ModelTypeSet::All().Equals(cryptographer->GetEncryptedTypes()));
205 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
206
207 Syncer::UnsyncedMetaHandles handles;
208 GetUnsyncedEntries(&trans, &handles);
209 EXPECT_EQ(2*batch_s+1, handles.size());
210 }
211
212 // Simulate another nigori update that doesn't change anything.
213 {
214 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory());
215 MutableEntry entry(&trans, syncable::GET_BY_SERVER_TAG,
216 ModelTypeToRootTag(NIGORI));
217 ASSERT_TRUE(entry.good());
218 entry.Put(syncable::SERVER_VERSION, entry_factory_->GetNextRevision());
219 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true);
220 }
221
222 ApplyControlDataUpdates(directory());
223
224 EXPECT_FALSE(cryptographer->has_pending_keys());
225 EXPECT_TRUE(cryptographer->is_ready());
226 {
227 syncable::ReadTransaction trans(FROM_HERE, directory());
228
229 // All our changes should still be encrypted.
230 EXPECT_TRUE(ModelTypeSet::All().Equals(cryptographer->GetEncryptedTypes()));
231 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
232
233 Syncer::UnsyncedMetaHandles handles;
234 GetUnsyncedEntries(&trans, &handles);
235 EXPECT_EQ(2*batch_s+1, handles.size());
236 }
237 }
238
239 TEST_F(ApplyControlDataUpdatesTest, CannotEncryptUnsyncedChanges) {
240 // Storing the cryptographer separately is bad, but for this test we
241 // know it's safe.
242 Cryptographer* cryptographer;
243 ModelTypeSet encrypted_types;
244 encrypted_types.Put(PASSWORDS);
245 encrypted_types.Put(NIGORI);
246 {
247 syncable::ReadTransaction trans(FROM_HERE, directory());
248 cryptographer = directory()->GetCryptographer(&trans);
249 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types));
250
251 // With default encrypted_types, this should be true.
252 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
253
254 Syncer::UnsyncedMetaHandles handles;
255 GetUnsyncedEntries(&trans, &handles);
256 EXPECT_TRUE(handles.empty());
257 }
258
259 // Create unsynced bookmarks without encryption.
260 // First item is a folder
261 Id folder_id = id_factory_.NewLocalId();
262 entry_factory_->CreateUnsyncedItem(
263 folder_id, id_factory_.root(), "folder", true,
264 BOOKMARKS, NULL);
265 // Next five items are children of the folder
266 size_t i;
267 size_t batch_s = 5;
268 for (i = 0; i < batch_s; ++i) {
269 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
270 base::StringPrintf("Item %"PRIuS"", i),
271 false, BOOKMARKS, NULL);
272 }
273 // Next five items are children of the root.
274 for (; i < 2*batch_s; ++i) {
275 entry_factory_->CreateUnsyncedItem(
276 id_factory_.NewLocalId(), id_factory_.root(),
277 base::StringPrintf("Item %"PRIuS"", i), false,
278 BOOKMARKS, NULL);
279 }
280
281 // We encrypt with new keys, triggering the local cryptographer to be unready
282 // and unable to decrypt data (once updated).
283 Cryptographer other_cryptographer(&encryptor_);
284 KeyParams params = {"localhost", "dummy", "foobar"};
285 other_cryptographer.AddKey(params);
286 sync_pb::EntitySpecifics specifics;
287 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
288 other_cryptographer.GetKeys(nigori->mutable_encrypted());
289 nigori->set_encrypt_bookmarks(true);
290 encrypted_types.Put(BOOKMARKS);
291 entry_factory_->CreateUnappliedNewItem(
292 ModelTypeToRootTag(NIGORI), specifics, true);
293 EXPECT_FALSE(cryptographer->has_pending_keys());
294
295 {
296 // Ensure we have unsynced nodes that aren't properly encrypted.
297 syncable::ReadTransaction trans(FROM_HERE, directory());
298 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
299 Syncer::UnsyncedMetaHandles handles;
300 GetUnsyncedEntries(&trans, &handles);
301 EXPECT_EQ(2*batch_s+1, handles.size());
302 }
303
304 ApplyControlDataUpdates(directory());
305
306 EXPECT_FALSE(cryptographer->is_ready());
307 EXPECT_TRUE(cryptographer->has_pending_keys());
308 {
309 syncable::ReadTransaction trans(FROM_HERE, directory());
310
311 // Since we have pending keys, we would have failed to encrypt, but the
312 // cryptographer should be updated.
313 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
314 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(
315 ModelTypeSet().All()));
316 EXPECT_FALSE(cryptographer->is_ready());
317 EXPECT_TRUE(cryptographer->has_pending_keys());
318
319 Syncer::UnsyncedMetaHandles handles;
320 GetUnsyncedEntries(&trans, &handles);
321 EXPECT_EQ(2*batch_s+1, handles.size());
322 }
323 }
324
325 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698