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

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

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

Powered by Google App Engine
This is Rietveld 408576698