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

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: Rebase 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/test/fake_encryptor.h"
23 #include "sync/test/fake_sync_encryption_handler.h"
24 #include "sync/util/cryptographer.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 namespace syncer {
28
29 using syncable::MutableEntry;
30 using syncable::UNITTEST;
31 using syncable::Id;
32
33 class ApplyControlDataUpdatesTest : public SyncerCommandTest {
34 public:
35 protected:
36 ApplyControlDataUpdatesTest() {}
37 virtual ~ApplyControlDataUpdatesTest() {}
38
39 virtual void SetUp() {
40 workers()->clear();
41 mutable_routing_info()->clear();
42 workers()->push_back(make_scoped_refptr(new FakeModelWorker(GROUP_UI)));
43 workers()->push_back(
44 make_scoped_refptr(new FakeModelWorker(GROUP_PASSWORD)));
45 (*mutable_routing_info())[BOOKMARKS] = GROUP_UI;
46 (*mutable_routing_info())[PASSWORDS] = GROUP_PASSWORD;
47 (*mutable_routing_info())[NIGORI] = GROUP_CONTROL;
48 SyncerCommandTest::SetUp();
49 entry_factory_.reset(new TestEntryFactory(directory()));
50
51 syncable::ReadTransaction trans(FROM_HERE, directory());
52 directory()->GetCryptographer(&trans)->SetNigoriHandler(
53 &fake_encryption_handler_);
54 fake_encryption_handler_.set_cryptographer(
55 directory()->GetCryptographer(&trans));
56 }
57
58 FakeEncryptor encryptor_;
59 TestIdFactory id_factory_;
60 scoped_ptr<TestEntryFactory> entry_factory_;
61 FakeSyncEncryptionHandler fake_encryption_handler_;
62 private:
63 DISALLOW_COPY_AND_ASSIGN(ApplyControlDataUpdatesTest);
64 };
65
66 TEST_F(ApplyControlDataUpdatesTest, NigoriUpdate) {
67 // Storing the cryptographer separately is bad, but for this test we
68 // know it's safe.
69 Cryptographer* cryptographer;
70 ModelTypeSet encrypted_types;
71 encrypted_types.Put(PASSWORDS);
72 encrypted_types.Put(NIGORI);
73 {
74 syncable::ReadTransaction trans(FROM_HERE, directory());
75 cryptographer = directory()->GetCryptographer(&trans);
76 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types));
77 }
78
79 // Nigori node updates should update the Cryptographer.
80 Cryptographer other_cryptographer(&encryptor_);
81 KeyParams params = {"localhost", "dummy", "foobar"};
82 other_cryptographer.AddKey(params);
83
84 sync_pb::EntitySpecifics specifics;
85 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
86 other_cryptographer.GetKeys(nigori->mutable_encrypted());
87 nigori->set_encrypt_everything(true);
88 entry_factory_->CreateUnappliedNewItem(
89 ModelTypeToRootTag(NIGORI), specifics, true);
90 EXPECT_FALSE(cryptographer->has_pending_keys());
91
92 ApplyControlDataUpdates(directory());
93
94 EXPECT_FALSE(cryptographer->is_ready());
95 EXPECT_TRUE(cryptographer->has_pending_keys());
96 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(ModelTypeSet::All()));
97 }
98
99 TEST_F(ApplyControlDataUpdatesTest, NigoriUpdateForDisabledTypes) {
100 // Storing the cryptographer separately is bad, but for this test we
101 // know it's safe.
102 Cryptographer* cryptographer;
103 ModelTypeSet encrypted_types;
104 encrypted_types.Put(PASSWORDS);
105 encrypted_types.Put(NIGORI);
106 {
107 syncable::ReadTransaction trans(FROM_HERE, directory());
108 cryptographer = directory()->GetCryptographer(&trans);
109 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types));
110 }
111
112 // Nigori node updates should update the Cryptographer.
113 Cryptographer other_cryptographer(&encryptor_);
114 KeyParams params = {"localhost", "dummy", "foobar"};
115 other_cryptographer.AddKey(params);
116
117 sync_pb::EntitySpecifics specifics;
118 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
119 other_cryptographer.GetKeys(nigori->mutable_encrypted());
120 nigori->set_encrypt_everything(true);
121 entry_factory_->CreateUnappliedNewItem(
122 ModelTypeToRootTag(NIGORI), specifics, true);
123 EXPECT_FALSE(cryptographer->has_pending_keys());
124
125 ApplyControlDataUpdates(directory());
126
127 EXPECT_FALSE(cryptographer->is_ready());
128 EXPECT_TRUE(cryptographer->has_pending_keys());
129 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(ModelTypeSet::All()));
130 }
131
132 // Create some local unsynced and unencrypted data. Apply a nigori update that
133 // turns on encryption for the unsynced data. Ensure we properly encrypt the
134 // data as part of the nigori update. Apply another nigori update with no
135 // changes. Ensure we ignore already-encrypted unsynced data and that nothing
136 // breaks.
137 TEST_F(ApplyControlDataUpdatesTest, EncryptUnsyncedChanges) {
138 // Storing the cryptographer separately is bad, but for this test we
139 // know it's safe.
140 Cryptographer* cryptographer;
141 ModelTypeSet encrypted_types;
142 encrypted_types.Put(PASSWORDS);
143 encrypted_types.Put(NIGORI);
144 {
145 syncable::ReadTransaction trans(FROM_HERE, directory());
146 cryptographer = directory()->GetCryptographer(&trans);
147 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types));
148
149 // With default encrypted_types, this should be true.
150 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
151
152 Syncer::UnsyncedMetaHandles handles;
153 GetUnsyncedEntries(&trans, &handles);
154 EXPECT_TRUE(handles.empty());
155 }
156
157 // Create unsynced bookmarks without encryption.
158 // First item is a folder
159 Id folder_id = id_factory_.NewLocalId();
160 entry_factory_->CreateUnsyncedItem(folder_id, id_factory_.root(), "folder",
161 true, BOOKMARKS, NULL);
162 // Next five items are children of the folder
163 size_t i;
164 size_t batch_s = 5;
165 for (i = 0; i < batch_s; ++i) {
166 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
167 base::StringPrintf("Item %"PRIuS"", i),
168 false, BOOKMARKS, NULL);
169 }
170 // Next five items are children of the root.
171 for (; i < 2*batch_s; ++i) {
172 entry_factory_->CreateUnsyncedItem(
173 id_factory_.NewLocalId(), id_factory_.root(),
174 base::StringPrintf("Item %"PRIuS"", i), false,
175 BOOKMARKS, NULL);
176 }
177
178 KeyParams params = {"localhost", "dummy", "foobar"};
179 cryptographer->AddKey(params);
180 sync_pb::EntitySpecifics specifics;
181 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
182 cryptographer->GetKeys(nigori->mutable_encrypted());
183 nigori->set_encrypt_everything(true);
184 encrypted_types.Put(BOOKMARKS);
185 entry_factory_->CreateUnappliedNewItem(
186 ModelTypeToRootTag(NIGORI), specifics, true);
187 EXPECT_FALSE(cryptographer->has_pending_keys());
188 EXPECT_TRUE(cryptographer->is_ready());
189
190 {
191 // Ensure we have unsynced nodes that aren't properly encrypted.
192 syncable::ReadTransaction trans(FROM_HERE, directory());
193 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
194
195 Syncer::UnsyncedMetaHandles handles;
196 GetUnsyncedEntries(&trans, &handles);
197 EXPECT_EQ(2*batch_s+1, handles.size());
198 }
199
200 ApplyControlDataUpdates(directory());
201
202 EXPECT_FALSE(cryptographer->has_pending_keys());
203 EXPECT_TRUE(cryptographer->is_ready());
204 {
205 syncable::ReadTransaction trans(FROM_HERE, directory());
206
207 // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes
208 // should be encrypted now.
209 EXPECT_TRUE(ModelTypeSet::All().Equals(cryptographer->GetEncryptedTypes()));
210 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
211
212 Syncer::UnsyncedMetaHandles handles;
213 GetUnsyncedEntries(&trans, &handles);
214 EXPECT_EQ(2*batch_s+1, handles.size());
215 }
216
217 // Simulate another nigori update that doesn't change anything.
218 {
219 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory());
220 MutableEntry entry(&trans, syncable::GET_BY_SERVER_TAG,
221 ModelTypeToRootTag(NIGORI));
222 ASSERT_TRUE(entry.good());
223 entry.Put(syncable::SERVER_VERSION, entry_factory_->GetNextRevision());
224 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true);
225 }
226
227 ApplyControlDataUpdates(directory());
228
229 EXPECT_FALSE(cryptographer->has_pending_keys());
230 EXPECT_TRUE(cryptographer->is_ready());
231 {
232 syncable::ReadTransaction trans(FROM_HERE, directory());
233
234 // All our changes should still be encrypted.
235 EXPECT_TRUE(ModelTypeSet::All().Equals(cryptographer->GetEncryptedTypes()));
236 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
237
238 Syncer::UnsyncedMetaHandles handles;
239 GetUnsyncedEntries(&trans, &handles);
240 EXPECT_EQ(2*batch_s+1, handles.size());
241 }
242 }
243
244 TEST_F(ApplyControlDataUpdatesTest, CannotEncryptUnsyncedChanges) {
245 // Storing the cryptographer separately is bad, but for this test we
246 // know it's safe.
247 Cryptographer* cryptographer;
248 ModelTypeSet encrypted_types;
249 encrypted_types.Put(PASSWORDS);
250 encrypted_types.Put(NIGORI);
251 {
252 syncable::ReadTransaction trans(FROM_HERE, directory());
253 cryptographer = directory()->GetCryptographer(&trans);
254 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types));
255
256 // With default encrypted_types, this should be true.
257 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
258
259 Syncer::UnsyncedMetaHandles handles;
260 GetUnsyncedEntries(&trans, &handles);
261 EXPECT_TRUE(handles.empty());
262 }
263
264 // Create unsynced bookmarks without encryption.
265 // First item is a folder
266 Id folder_id = id_factory_.NewLocalId();
267 entry_factory_->CreateUnsyncedItem(
268 folder_id, id_factory_.root(), "folder", true,
269 BOOKMARKS, NULL);
270 // Next five items are children of the folder
271 size_t i;
272 size_t batch_s = 5;
273 for (i = 0; i < batch_s; ++i) {
274 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
275 base::StringPrintf("Item %"PRIuS"", i),
276 false, BOOKMARKS, NULL);
277 }
278 // Next five items are children of the root.
279 for (; i < 2*batch_s; ++i) {
280 entry_factory_->CreateUnsyncedItem(
281 id_factory_.NewLocalId(), id_factory_.root(),
282 base::StringPrintf("Item %"PRIuS"", i), false,
283 BOOKMARKS, NULL);
284 }
285
286 // We encrypt with new keys, triggering the local cryptographer to be unready
287 // and unable to decrypt data (once updated).
288 Cryptographer other_cryptographer(&encryptor_);
289 KeyParams params = {"localhost", "dummy", "foobar"};
290 other_cryptographer.AddKey(params);
291 sync_pb::EntitySpecifics specifics;
292 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
293 other_cryptographer.GetKeys(nigori->mutable_encrypted());
294 nigori->set_encrypt_everything(true);
295 encrypted_types.Put(BOOKMARKS);
296 entry_factory_->CreateUnappliedNewItem(
297 ModelTypeToRootTag(NIGORI), specifics, true);
298 EXPECT_FALSE(cryptographer->has_pending_keys());
299
300 {
301 // Ensure we have unsynced nodes that aren't properly encrypted.
302 syncable::ReadTransaction trans(FROM_HERE, directory());
303 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
304 Syncer::UnsyncedMetaHandles handles;
305 GetUnsyncedEntries(&trans, &handles);
306 EXPECT_EQ(2*batch_s+1, handles.size());
307 }
308
309 ApplyControlDataUpdates(directory());
310
311 EXPECT_FALSE(cryptographer->is_ready());
312 EXPECT_TRUE(cryptographer->has_pending_keys());
313 {
314 syncable::ReadTransaction trans(FROM_HERE, directory());
315
316 // Since we have pending keys, we would have failed to encrypt, but the
317 // cryptographer should be updated.
318 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
319 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(
320 ModelTypeSet().All()));
321 EXPECT_FALSE(cryptographer->is_ready());
322 EXPECT_TRUE(cryptographer->has_pending_keys());
323
324 Syncer::UnsyncedMetaHandles handles;
325 GetUnsyncedEntries(&trans, &handles);
326 EXPECT_EQ(2*batch_s+1, handles.size());
327 }
328 }
329
330 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698