Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / sync / internal_api / sync_manager_impl_unittest.cc
1 // Copyright 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 // Unit tests for the SyncApi. Note that a lot of the underlying
6 // functionality is provided by the Syncable layer, which has its own
7 // unit tests. We'll test SyncApi specific things in this harness.
8
9 #include <cstddef>
10 #include <map>
11
12 #include "base/basictypes.h"
13 #include "base/callback.h"
14 #include "base/compiler_specific.h"
15 #include "base/files/scoped_temp_dir.h"
16 #include "base/format_macros.h"
17 #include "base/location.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/message_loop/message_loop.h"
20 #include "base/message_loop/message_loop_proxy.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/test/values_test_util.h"
25 #include "base/values.h"
26 #include "sync/engine/sync_scheduler.h"
27 #include "sync/internal_api/public/base/cancelation_signal.h"
28 #include "sync/internal_api/public/base/model_type_test_util.h"
29 #include "sync/internal_api/public/change_record.h"
30 #include "sync/internal_api/public/engine/model_safe_worker.h"
31 #include "sync/internal_api/public/engine/polling_constants.h"
32 #include "sync/internal_api/public/events/protocol_event.h"
33 #include "sync/internal_api/public/http_post_provider_factory.h"
34 #include "sync/internal_api/public/http_post_provider_interface.h"
35 #include "sync/internal_api/public/read_node.h"
36 #include "sync/internal_api/public/read_transaction.h"
37 #include "sync/internal_api/public/test/test_entry_factory.h"
38 #include "sync/internal_api/public/test/test_internal_components_factory.h"
39 #include "sync/internal_api/public/test/test_user_share.h"
40 #include "sync/internal_api/public/write_node.h"
41 #include "sync/internal_api/public/write_transaction.h"
42 #include "sync/internal_api/sync_encryption_handler_impl.h"
43 #include "sync/internal_api/sync_manager_impl.h"
44 #include "sync/internal_api/syncapi_internal.h"
45 #include "sync/js/js_backend.h"
46 #include "sync/js/js_event_handler.h"
47 #include "sync/js/js_test_util.h"
48 #include "sync/notifier/fake_invalidation_handler.h"
49 #include "sync/notifier/invalidation_handler.h"
50 #include "sync/notifier/invalidator.h"
51 #include "sync/protocol/bookmark_specifics.pb.h"
52 #include "sync/protocol/encryption.pb.h"
53 #include "sync/protocol/extension_specifics.pb.h"
54 #include "sync/protocol/password_specifics.pb.h"
55 #include "sync/protocol/preference_specifics.pb.h"
56 #include "sync/protocol/proto_value_conversions.h"
57 #include "sync/protocol/sync.pb.h"
58 #include "sync/sessions/sync_session.h"
59 #include "sync/syncable/directory.h"
60 #include "sync/syncable/entry.h"
61 #include "sync/syncable/mutable_entry.h"
62 #include "sync/syncable/nigori_util.h"
63 #include "sync/syncable/syncable_id.h"
64 #include "sync/syncable/syncable_read_transaction.h"
65 #include "sync/syncable/syncable_util.h"
66 #include "sync/syncable/syncable_write_transaction.h"
67 #include "sync/test/callback_counter.h"
68 #include "sync/test/engine/fake_model_worker.h"
69 #include "sync/test/engine/fake_sync_scheduler.h"
70 #include "sync/test/engine/test_id_factory.h"
71 #include "sync/test/fake_encryptor.h"
72 #include "sync/util/cryptographer.h"
73 #include "sync/util/extensions_activity.h"
74 #include "sync/util/test_unrecoverable_error_handler.h"
75 #include "sync/util/time.h"
76 #include "testing/gmock/include/gmock/gmock.h"
77 #include "testing/gtest/include/gtest/gtest.h"
78
79 using base::ExpectDictStringValue;
80 using testing::_;
81 using testing::DoAll;
82 using testing::InSequence;
83 using testing::Return;
84 using testing::SaveArg;
85 using testing::StrictMock;
86
87 namespace syncer {
88
89 using sessions::SyncSessionSnapshot;
90 using syncable::GET_BY_HANDLE;
91 using syncable::IS_DEL;
92 using syncable::IS_UNSYNCED;
93 using syncable::NON_UNIQUE_NAME;
94 using syncable::SPECIFICS;
95 using syncable::kEncryptedString;
96
97 namespace {
98
99 // Makes a non-folder child of the root node.  Returns the id of the
100 // newly-created node.
101 int64 MakeNode(UserShare* share,
102                ModelType model_type,
103                const std::string& client_tag) {
104   WriteTransaction trans(FROM_HERE, share);
105   ReadNode root_node(&trans);
106   root_node.InitByRootLookup();
107   WriteNode node(&trans);
108   WriteNode::InitUniqueByCreationResult result =
109       node.InitUniqueByCreation(model_type, root_node, client_tag);
110   EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
111   node.SetIsFolder(false);
112   return node.GetId();
113 }
114
115 // Makes a folder child of a non-root node. Returns the id of the
116 // newly-created node.
117 int64 MakeFolderWithParent(UserShare* share,
118                            ModelType model_type,
119                            int64 parent_id,
120                            BaseNode* predecessor) {
121   WriteTransaction trans(FROM_HERE, share);
122   ReadNode parent_node(&trans);
123   EXPECT_EQ(BaseNode::INIT_OK, parent_node.InitByIdLookup(parent_id));
124   WriteNode node(&trans);
125   EXPECT_TRUE(node.InitBookmarkByCreation(parent_node, predecessor));
126   node.SetIsFolder(true);
127   return node.GetId();
128 }
129
130 int64 MakeBookmarkWithParent(UserShare* share,
131                              int64 parent_id,
132                              BaseNode* predecessor) {
133   WriteTransaction trans(FROM_HERE, share);
134   ReadNode parent_node(&trans);
135   EXPECT_EQ(BaseNode::INIT_OK, parent_node.InitByIdLookup(parent_id));
136   WriteNode node(&trans);
137   EXPECT_TRUE(node.InitBookmarkByCreation(parent_node, predecessor));
138   return node.GetId();
139 }
140
141 // Creates the "synced" root node for a particular datatype. We use the syncable
142 // methods here so that the syncer treats these nodes as if they were already
143 // received from the server.
144 int64 MakeServerNodeForType(UserShare* share,
145                             ModelType model_type) {
146   sync_pb::EntitySpecifics specifics;
147   AddDefaultFieldValue(model_type, &specifics);
148   syncable::WriteTransaction trans(
149       FROM_HERE, syncable::UNITTEST, share->directory.get());
150   // Attempt to lookup by nigori tag.
151   std::string type_tag = ModelTypeToRootTag(model_type);
152   syncable::Id node_id = syncable::Id::CreateFromServerId(type_tag);
153   syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
154                                node_id);
155   EXPECT_TRUE(entry.good());
156   entry.PutBaseVersion(1);
157   entry.PutServerVersion(1);
158   entry.PutIsUnappliedUpdate(false);
159   entry.PutServerParentId(syncable::GetNullId());
160   entry.PutServerIsDir(true);
161   entry.PutIsDir(true);
162   entry.PutServerSpecifics(specifics);
163   entry.PutUniqueServerTag(type_tag);
164   entry.PutNonUniqueName(type_tag);
165   entry.PutIsDel(false);
166   entry.PutSpecifics(specifics);
167   return entry.GetMetahandle();
168 }
169
170 // Simulates creating a "synced" node as a child of the root datatype node.
171 int64 MakeServerNode(UserShare* share, ModelType model_type,
172                      const std::string& client_tag,
173                      const std::string& hashed_tag,
174                      const sync_pb::EntitySpecifics& specifics) {
175   syncable::WriteTransaction trans(
176       FROM_HERE, syncable::UNITTEST, share->directory.get());
177   syncable::Entry root_entry(&trans, syncable::GET_BY_SERVER_TAG,
178                              ModelTypeToRootTag(model_type));
179   EXPECT_TRUE(root_entry.good());
180   syncable::Id root_id = root_entry.GetId();
181   syncable::Id node_id = syncable::Id::CreateFromServerId(client_tag);
182   syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
183                                node_id);
184   EXPECT_TRUE(entry.good());
185   entry.PutBaseVersion(1);
186   entry.PutServerVersion(1);
187   entry.PutIsUnappliedUpdate(false);
188   entry.PutServerParentId(root_id);
189   entry.PutParentId(root_id);
190   entry.PutServerIsDir(false);
191   entry.PutIsDir(false);
192   entry.PutServerSpecifics(specifics);
193   entry.PutNonUniqueName(client_tag);
194   entry.PutUniqueClientTag(hashed_tag);
195   entry.PutIsDel(false);
196   entry.PutSpecifics(specifics);
197   return entry.GetMetahandle();
198 }
199
200 }  // namespace
201
202 class SyncApiTest : public testing::Test {
203  public:
204   virtual void SetUp() {
205     test_user_share_.SetUp();
206   }
207
208   virtual void TearDown() {
209     test_user_share_.TearDown();
210   }
211
212  protected:
213   // Create an entry with the given |model_type|, |client_tag| and
214   // |attachment_metadata|.
215   void CreateEntryWithAttachmentMetadata(
216       const ModelType& model_type,
217       const std::string& client_tag,
218       const sync_pb::AttachmentMetadata& attachment_metadata);
219
220   // Attempts to load the entry specified by |model_type| and |client_tag| and
221   // returns the lookup result code.
222   BaseNode::InitByLookupResult LookupEntryByClientTag(
223       const ModelType& model_type,
224       const std::string& client_tag);
225
226   // Replace the entry specified by |model_type| and |client_tag| with a
227   // tombstone.
228   void ReplaceWithTombstone(const ModelType& model_type,
229                             const std::string& client_tag);
230
231   // Save changes to the Directory, destroy it then reload it.
232   bool ReloadDir();
233
234   UserShare* user_share();
235   syncable::Directory* dir();
236   SyncEncryptionHandler* encryption_handler();
237
238  private:
239   base::MessageLoop message_loop_;
240   TestUserShare test_user_share_;
241 };
242
243 UserShare* SyncApiTest::user_share() {
244   return test_user_share_.user_share();
245 }
246
247 syncable::Directory* SyncApiTest::dir() {
248   return test_user_share_.user_share()->directory.get();
249 }
250
251 SyncEncryptionHandler* SyncApiTest::encryption_handler() {
252   return test_user_share_.encryption_handler();
253 }
254
255 bool SyncApiTest::ReloadDir() {
256   return test_user_share_.Reload();
257 }
258
259 void SyncApiTest::CreateEntryWithAttachmentMetadata(
260     const ModelType& model_type,
261     const std::string& client_tag,
262     const sync_pb::AttachmentMetadata& attachment_metadata) {
263   syncer::WriteTransaction trans(FROM_HERE, user_share());
264   syncer::ReadNode root_node(&trans);
265   root_node.InitByRootLookup();
266   syncer::WriteNode node(&trans);
267   ASSERT_EQ(node.InitUniqueByCreation(model_type, root_node, client_tag),
268             syncer::WriteNode::INIT_SUCCESS);
269   node.SetAttachmentMetadata(attachment_metadata);
270 }
271
272 BaseNode::InitByLookupResult SyncApiTest::LookupEntryByClientTag(
273     const ModelType& model_type,
274     const std::string& client_tag) {
275   syncer::ReadTransaction trans(FROM_HERE, user_share());
276   syncer::ReadNode node(&trans);
277   return node.InitByClientTagLookup(model_type, client_tag);
278 }
279
280 void SyncApiTest::ReplaceWithTombstone(const ModelType& model_type,
281                                        const std::string& client_tag) {
282   syncer::WriteTransaction trans(FROM_HERE, user_share());
283   syncer::WriteNode node(&trans);
284   ASSERT_EQ(node.InitByClientTagLookup(model_type, client_tag),
285             syncer::WriteNode::INIT_OK);
286   node.Tombstone();
287 }
288
289 TEST_F(SyncApiTest, SanityCheckTest) {
290   {
291     ReadTransaction trans(FROM_HERE, user_share());
292     EXPECT_TRUE(trans.GetWrappedTrans());
293   }
294   {
295     WriteTransaction trans(FROM_HERE, user_share());
296     EXPECT_TRUE(trans.GetWrappedTrans());
297   }
298   {
299     // No entries but root should exist
300     ReadTransaction trans(FROM_HERE, user_share());
301     ReadNode node(&trans);
302     // Metahandle 1 can be root, sanity check 2
303     EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD, node.InitByIdLookup(2));
304   }
305 }
306
307 TEST_F(SyncApiTest, BasicTagWrite) {
308   {
309     ReadTransaction trans(FROM_HERE, user_share());
310     ReadNode root_node(&trans);
311     root_node.InitByRootLookup();
312     EXPECT_EQ(root_node.GetFirstChildId(), 0);
313   }
314
315   ignore_result(MakeNode(user_share(), BOOKMARKS, "testtag"));
316
317   {
318     ReadTransaction trans(FROM_HERE, user_share());
319     ReadNode node(&trans);
320     EXPECT_EQ(BaseNode::INIT_OK,
321               node.InitByClientTagLookup(BOOKMARKS, "testtag"));
322
323     ReadNode root_node(&trans);
324     root_node.InitByRootLookup();
325     EXPECT_NE(node.GetId(), 0);
326     EXPECT_EQ(node.GetId(), root_node.GetFirstChildId());
327   }
328 }
329
330 TEST_F(SyncApiTest, ModelTypesSiloed) {
331   {
332     WriteTransaction trans(FROM_HERE, user_share());
333     ReadNode root_node(&trans);
334     root_node.InitByRootLookup();
335     EXPECT_EQ(root_node.GetFirstChildId(), 0);
336   }
337
338   ignore_result(MakeNode(user_share(), BOOKMARKS, "collideme"));
339   ignore_result(MakeNode(user_share(), PREFERENCES, "collideme"));
340   ignore_result(MakeNode(user_share(), AUTOFILL, "collideme"));
341
342   {
343     ReadTransaction trans(FROM_HERE, user_share());
344
345     ReadNode bookmarknode(&trans);
346     EXPECT_EQ(BaseNode::INIT_OK,
347               bookmarknode.InitByClientTagLookup(BOOKMARKS,
348                   "collideme"));
349
350     ReadNode prefnode(&trans);
351     EXPECT_EQ(BaseNode::INIT_OK,
352               prefnode.InitByClientTagLookup(PREFERENCES,
353                   "collideme"));
354
355     ReadNode autofillnode(&trans);
356     EXPECT_EQ(BaseNode::INIT_OK,
357               autofillnode.InitByClientTagLookup(AUTOFILL,
358                   "collideme"));
359
360     EXPECT_NE(bookmarknode.GetId(), prefnode.GetId());
361     EXPECT_NE(autofillnode.GetId(), prefnode.GetId());
362     EXPECT_NE(bookmarknode.GetId(), autofillnode.GetId());
363   }
364 }
365
366 TEST_F(SyncApiTest, ReadMissingTagsFails) {
367   {
368     ReadTransaction trans(FROM_HERE, user_share());
369     ReadNode node(&trans);
370     EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD,
371               node.InitByClientTagLookup(BOOKMARKS,
372                   "testtag"));
373   }
374   {
375     WriteTransaction trans(FROM_HERE, user_share());
376     WriteNode node(&trans);
377     EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD,
378               node.InitByClientTagLookup(BOOKMARKS,
379                   "testtag"));
380   }
381 }
382
383 // TODO(chron): Hook this all up to the server and write full integration tests
384 //              for update->undelete behavior.
385 TEST_F(SyncApiTest, TestDeleteBehavior) {
386   int64 node_id;
387   int64 folder_id;
388   std::string test_title("test1");
389
390   {
391     WriteTransaction trans(FROM_HERE, user_share());
392     ReadNode root_node(&trans);
393     root_node.InitByRootLookup();
394
395     // we'll use this spare folder later
396     WriteNode folder_node(&trans);
397     EXPECT_TRUE(folder_node.InitBookmarkByCreation(root_node, NULL));
398     folder_id = folder_node.GetId();
399
400     WriteNode wnode(&trans);
401     WriteNode::InitUniqueByCreationResult result =
402         wnode.InitUniqueByCreation(BOOKMARKS, root_node, "testtag");
403     EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
404     wnode.SetIsFolder(false);
405     wnode.SetTitle(test_title);
406
407     node_id = wnode.GetId();
408   }
409
410   // Ensure we can delete something with a tag.
411   {
412     WriteTransaction trans(FROM_HERE, user_share());
413     WriteNode wnode(&trans);
414     EXPECT_EQ(BaseNode::INIT_OK,
415               wnode.InitByClientTagLookup(BOOKMARKS,
416                   "testtag"));
417     EXPECT_FALSE(wnode.GetIsFolder());
418     EXPECT_EQ(wnode.GetTitle(), test_title);
419
420     wnode.Tombstone();
421   }
422
423   // Lookup of a node which was deleted should return failure,
424   // but have found some data about the node.
425   {
426     ReadTransaction trans(FROM_HERE, user_share());
427     ReadNode node(&trans);
428     EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_IS_DEL,
429               node.InitByClientTagLookup(BOOKMARKS,
430                   "testtag"));
431     // Note that for proper function of this API this doesn't need to be
432     // filled, we're checking just to make sure the DB worked in this test.
433     EXPECT_EQ(node.GetTitle(), test_title);
434   }
435
436   {
437     WriteTransaction trans(FROM_HERE, user_share());
438     ReadNode folder_node(&trans);
439     EXPECT_EQ(BaseNode::INIT_OK, folder_node.InitByIdLookup(folder_id));
440
441     WriteNode wnode(&trans);
442     // This will undelete the tag.
443     WriteNode::InitUniqueByCreationResult result =
444         wnode.InitUniqueByCreation(BOOKMARKS, folder_node, "testtag");
445     EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
446     EXPECT_EQ(wnode.GetIsFolder(), false);
447     EXPECT_EQ(wnode.GetParentId(), folder_node.GetId());
448     EXPECT_EQ(wnode.GetId(), node_id);
449     EXPECT_NE(wnode.GetTitle(), test_title);  // Title should be cleared
450     wnode.SetTitle(test_title);
451   }
452
453   // Now look up should work.
454   {
455     ReadTransaction trans(FROM_HERE, user_share());
456     ReadNode node(&trans);
457     EXPECT_EQ(BaseNode::INIT_OK,
458               node.InitByClientTagLookup(BOOKMARKS,
459                     "testtag"));
460     EXPECT_EQ(node.GetTitle(), test_title);
461     EXPECT_EQ(node.GetModelType(), BOOKMARKS);
462   }
463 }
464
465 TEST_F(SyncApiTest, WriteAndReadPassword) {
466   KeyParams params = {"localhost", "username", "passphrase"};
467   {
468     ReadTransaction trans(FROM_HERE, user_share());
469     trans.GetCryptographer()->AddKey(params);
470   }
471   {
472     WriteTransaction trans(FROM_HERE, user_share());
473     ReadNode root_node(&trans);
474     root_node.InitByRootLookup();
475
476     WriteNode password_node(&trans);
477     WriteNode::InitUniqueByCreationResult result =
478         password_node.InitUniqueByCreation(PASSWORDS,
479                                            root_node, "foo");
480     EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
481     sync_pb::PasswordSpecificsData data;
482     data.set_password_value("secret");
483     password_node.SetPasswordSpecifics(data);
484   }
485   {
486     ReadTransaction trans(FROM_HERE, user_share());
487     ReadNode root_node(&trans);
488     root_node.InitByRootLookup();
489
490     ReadNode password_node(&trans);
491     EXPECT_EQ(BaseNode::INIT_OK,
492               password_node.InitByClientTagLookup(PASSWORDS, "foo"));
493     const sync_pb::PasswordSpecificsData& data =
494         password_node.GetPasswordSpecifics();
495     EXPECT_EQ("secret", data.password_value());
496   }
497 }
498
499 TEST_F(SyncApiTest, WriteEncryptedTitle) {
500   KeyParams params = {"localhost", "username", "passphrase"};
501   {
502     ReadTransaction trans(FROM_HERE, user_share());
503     trans.GetCryptographer()->AddKey(params);
504   }
505   encryption_handler()->EnableEncryptEverything();
506   int bookmark_id;
507   {
508     WriteTransaction trans(FROM_HERE, user_share());
509     ReadNode root_node(&trans);
510     root_node.InitByRootLookup();
511
512     WriteNode bookmark_node(&trans);
513     ASSERT_TRUE(bookmark_node.InitBookmarkByCreation(root_node, NULL));
514     bookmark_id = bookmark_node.GetId();
515     bookmark_node.SetTitle("foo");
516
517     WriteNode pref_node(&trans);
518     WriteNode::InitUniqueByCreationResult result =
519         pref_node.InitUniqueByCreation(PREFERENCES, root_node, "bar");
520     ASSERT_EQ(WriteNode::INIT_SUCCESS, result);
521     pref_node.SetTitle("bar");
522   }
523   {
524     ReadTransaction trans(FROM_HERE, user_share());
525     ReadNode root_node(&trans);
526     root_node.InitByRootLookup();
527
528     ReadNode bookmark_node(&trans);
529     ASSERT_EQ(BaseNode::INIT_OK, bookmark_node.InitByIdLookup(bookmark_id));
530     EXPECT_EQ("foo", bookmark_node.GetTitle());
531     EXPECT_EQ(kEncryptedString,
532               bookmark_node.GetEntry()->GetNonUniqueName());
533
534     ReadNode pref_node(&trans);
535     ASSERT_EQ(BaseNode::INIT_OK,
536               pref_node.InitByClientTagLookup(PREFERENCES,
537                                               "bar"));
538     EXPECT_EQ(kEncryptedString, pref_node.GetTitle());
539   }
540 }
541
542 TEST_F(SyncApiTest, BaseNodeSetSpecifics) {
543   int64 child_id = MakeNode(user_share(), BOOKMARKS, "testtag");
544   WriteTransaction trans(FROM_HERE, user_share());
545   WriteNode node(&trans);
546   EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(child_id));
547
548   sync_pb::EntitySpecifics entity_specifics;
549   entity_specifics.mutable_bookmark()->set_url("http://www.google.com");
550
551   EXPECT_NE(entity_specifics.SerializeAsString(),
552             node.GetEntitySpecifics().SerializeAsString());
553   node.SetEntitySpecifics(entity_specifics);
554   EXPECT_EQ(entity_specifics.SerializeAsString(),
555             node.GetEntitySpecifics().SerializeAsString());
556 }
557
558 TEST_F(SyncApiTest, BaseNodeSetSpecificsPreservesUnknownFields) {
559   int64 child_id = MakeNode(user_share(), BOOKMARKS, "testtag");
560   WriteTransaction trans(FROM_HERE, user_share());
561   WriteNode node(&trans);
562   EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(child_id));
563   EXPECT_TRUE(node.GetEntitySpecifics().unknown_fields().empty());
564
565   sync_pb::EntitySpecifics entity_specifics;
566   entity_specifics.mutable_bookmark()->set_url("http://www.google.com");
567   entity_specifics.mutable_unknown_fields()->AddFixed32(5, 100);
568   node.SetEntitySpecifics(entity_specifics);
569   EXPECT_FALSE(node.GetEntitySpecifics().unknown_fields().empty());
570
571   entity_specifics.mutable_unknown_fields()->Clear();
572   node.SetEntitySpecifics(entity_specifics);
573   EXPECT_FALSE(node.GetEntitySpecifics().unknown_fields().empty());
574 }
575
576 TEST_F(SyncApiTest, EmptyTags) {
577   WriteTransaction trans(FROM_HERE, user_share());
578   ReadNode root_node(&trans);
579   root_node.InitByRootLookup();
580   WriteNode node(&trans);
581   std::string empty_tag;
582   WriteNode::InitUniqueByCreationResult result =
583       node.InitUniqueByCreation(TYPED_URLS, root_node, empty_tag);
584   EXPECT_NE(WriteNode::INIT_SUCCESS, result);
585   EXPECT_EQ(BaseNode::INIT_FAILED_PRECONDITION,
586             node.InitByTagLookup(empty_tag));
587 }
588
589 // Test counting nodes when the type's root node has no children.
590 TEST_F(SyncApiTest, GetTotalNodeCountEmpty) {
591   int64 type_root = MakeServerNodeForType(user_share(), BOOKMARKS);
592   {
593     ReadTransaction trans(FROM_HERE, user_share());
594     ReadNode type_root_node(&trans);
595     EXPECT_EQ(BaseNode::INIT_OK,
596               type_root_node.InitByIdLookup(type_root));
597     EXPECT_EQ(1, type_root_node.GetTotalNodeCount());
598   }
599 }
600
601 // Test counting nodes when there is one child beneath the type's root.
602 TEST_F(SyncApiTest, GetTotalNodeCountOneChild) {
603   int64 type_root = MakeServerNodeForType(user_share(), BOOKMARKS);
604   int64 parent = MakeFolderWithParent(user_share(), BOOKMARKS, type_root, NULL);
605   {
606     ReadTransaction trans(FROM_HERE, user_share());
607     ReadNode type_root_node(&trans);
608     EXPECT_EQ(BaseNode::INIT_OK,
609               type_root_node.InitByIdLookup(type_root));
610     EXPECT_EQ(2, type_root_node.GetTotalNodeCount());
611     ReadNode parent_node(&trans);
612     EXPECT_EQ(BaseNode::INIT_OK,
613               parent_node.InitByIdLookup(parent));
614     EXPECT_EQ(1, parent_node.GetTotalNodeCount());
615   }
616 }
617
618 // Test counting nodes when there are multiple children beneath the type root,
619 // and one of those children has children of its own.
620 TEST_F(SyncApiTest, GetTotalNodeCountMultipleChildren) {
621   int64 type_root = MakeServerNodeForType(user_share(), BOOKMARKS);
622   int64 parent = MakeFolderWithParent(user_share(), BOOKMARKS, type_root, NULL);
623   ignore_result(MakeFolderWithParent(user_share(), BOOKMARKS, type_root, NULL));
624   int64 child1 = MakeFolderWithParent(user_share(), BOOKMARKS, parent, NULL);
625   ignore_result(MakeBookmarkWithParent(user_share(), parent, NULL));
626   ignore_result(MakeBookmarkWithParent(user_share(), child1, NULL));
627
628   {
629     ReadTransaction trans(FROM_HERE, user_share());
630     ReadNode type_root_node(&trans);
631     EXPECT_EQ(BaseNode::INIT_OK,
632               type_root_node.InitByIdLookup(type_root));
633     EXPECT_EQ(6, type_root_node.GetTotalNodeCount());
634     ReadNode node(&trans);
635     EXPECT_EQ(BaseNode::INIT_OK,
636               node.InitByIdLookup(parent));
637     EXPECT_EQ(4, node.GetTotalNodeCount());
638   }
639 }
640
641 // Verify that Directory keeps track of which attachments are referenced by
642 // which entries.
643 TEST_F(SyncApiTest, AttachmentLinking) {
644   // Add an entry with an attachment.
645   std::string tag1("some tag");
646   syncer::AttachmentId attachment_id(syncer::AttachmentId::Create());
647   sync_pb::AttachmentMetadata attachment_metadata;
648   sync_pb::AttachmentMetadataRecord* record = attachment_metadata.add_record();
649   *record->mutable_id() = attachment_id.GetProto();
650   ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id.GetProto()));
651   CreateEntryWithAttachmentMetadata(PREFERENCES, tag1, attachment_metadata);
652
653   // See that the directory knows it's linked.
654   ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));
655
656   // Add a second entry referencing the same attachment.
657   std::string tag2("some other tag");
658   CreateEntryWithAttachmentMetadata(PREFERENCES, tag2, attachment_metadata);
659
660   // See that the directory knows it's still linked.
661   ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));
662
663   // Tombstone the first entry.
664   ReplaceWithTombstone(syncer::PREFERENCES, tag1);
665
666   // See that the attachment is still considered linked because the entry hasn't
667   // been purged from the Directory.
668   ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));
669
670   // Save changes and see that the entry is truly gone.
671   ASSERT_TRUE(dir()->SaveChanges());
672   ASSERT_EQ(LookupEntryByClientTag(PREFERENCES, tag1),
673             syncer::WriteNode::INIT_FAILED_ENTRY_NOT_GOOD);
674
675   // However, the attachment is still linked.
676   ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));
677
678   // Save, destroy, and recreate the directory.  See that it's still linked.
679   ASSERT_TRUE(ReloadDir());
680   ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));
681
682   // Tombstone the second entry, save changes, see that it's truly gone.
683   ReplaceWithTombstone(syncer::PREFERENCES, tag2);
684   ASSERT_TRUE(dir()->SaveChanges());
685   ASSERT_EQ(LookupEntryByClientTag(PREFERENCES, tag2),
686             syncer::WriteNode::INIT_FAILED_ENTRY_NOT_GOOD);
687
688   // Finally, the attachment is no longer linked.
689   ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id.GetProto()));
690 }
691
692 namespace {
693
694 class TestHttpPostProviderInterface : public HttpPostProviderInterface {
695  public:
696   virtual ~TestHttpPostProviderInterface() {}
697
698   virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE {}
699   virtual void SetURL(const char* url, int port) OVERRIDE {}
700   virtual void SetPostPayload(const char* content_type,
701                               int content_length,
702                               const char* content) OVERRIDE {}
703   virtual bool MakeSynchronousPost(int* error_code, int* response_code)
704       OVERRIDE {
705     return false;
706   }
707   virtual int GetResponseContentLength() const OVERRIDE {
708     return 0;
709   }
710   virtual const char* GetResponseContent() const OVERRIDE {
711     return "";
712   }
713   virtual const std::string GetResponseHeaderValue(
714       const std::string& name) const OVERRIDE {
715     return std::string();
716   }
717   virtual void Abort() OVERRIDE {}
718 };
719
720 class TestHttpPostProviderFactory : public HttpPostProviderFactory {
721  public:
722   virtual ~TestHttpPostProviderFactory() {}
723   virtual void Init(const std::string& user_agent) OVERRIDE { }
724   virtual HttpPostProviderInterface* Create() OVERRIDE {
725     return new TestHttpPostProviderInterface();
726   }
727   virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE {
728     delete static_cast<TestHttpPostProviderInterface*>(http);
729   }
730 };
731
732 class SyncManagerObserverMock : public SyncManager::Observer {
733  public:
734   MOCK_METHOD1(OnSyncCycleCompleted,
735                void(const SyncSessionSnapshot&));  // NOLINT
736   MOCK_METHOD4(OnInitializationComplete,
737                void(const WeakHandle<JsBackend>&,
738                     const WeakHandle<DataTypeDebugInfoListener>&,
739                     bool,
740                     syncer::ModelTypeSet));  // NOLINT
741   MOCK_METHOD1(OnConnectionStatusChange, void(ConnectionStatus));  // NOLINT
742   MOCK_METHOD1(OnUpdatedToken, void(const std::string&));  // NOLINT
743   MOCK_METHOD1(OnActionableError, void(const SyncProtocolError&));  // NOLINT
744   MOCK_METHOD1(OnMigrationRequested, void(syncer::ModelTypeSet));  // NOLINT
745   MOCK_METHOD1(OnProtocolEvent, void(const ProtocolEvent&));  // NOLINT
746 };
747
748 class SyncEncryptionHandlerObserverMock
749     : public SyncEncryptionHandler::Observer {
750  public:
751   MOCK_METHOD2(OnPassphraseRequired,
752                void(PassphraseRequiredReason,
753                     const sync_pb::EncryptedData&));  // NOLINT
754   MOCK_METHOD0(OnPassphraseAccepted, void());  // NOLINT
755   MOCK_METHOD2(OnBootstrapTokenUpdated,
756                void(const std::string&, BootstrapTokenType type));  // NOLINT
757   MOCK_METHOD2(OnEncryptedTypesChanged,
758                void(ModelTypeSet, bool));  // NOLINT
759   MOCK_METHOD0(OnEncryptionComplete, void());  // NOLINT
760   MOCK_METHOD1(OnCryptographerStateChanged, void(Cryptographer*));  // NOLINT
761   MOCK_METHOD2(OnPassphraseTypeChanged, void(PassphraseType,
762                                              base::Time));  // NOLINT
763 };
764
765 }  // namespace
766
767 class SyncManagerTest : public testing::Test,
768                         public SyncManager::ChangeDelegate {
769  protected:
770   enum NigoriStatus {
771     DONT_WRITE_NIGORI,
772     WRITE_TO_NIGORI
773   };
774
775   enum EncryptionStatus {
776     UNINITIALIZED,
777     DEFAULT_ENCRYPTION,
778     FULL_ENCRYPTION
779   };
780
781   SyncManagerTest()
782       : sync_manager_("Test sync manager") {
783     switches_.encryption_method =
784         InternalComponentsFactory::ENCRYPTION_KEYSTORE;
785   }
786
787   virtual ~SyncManagerTest() {
788   }
789
790   // Test implementation.
791   void SetUp() {
792     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
793
794     extensions_activity_ = new ExtensionsActivity();
795
796     SyncCredentials credentials;
797     credentials.email = "foo@bar.com";
798     credentials.sync_token = "sometoken";
799
800     sync_manager_.AddObserver(&manager_observer_);
801     EXPECT_CALL(manager_observer_, OnInitializationComplete(_, _, _, _)).
802         WillOnce(DoAll(SaveArg<0>(&js_backend_),
803             SaveArg<2>(&initialization_succeeded_)));
804
805     EXPECT_FALSE(js_backend_.IsInitialized());
806
807     std::vector<scoped_refptr<ModelSafeWorker> > workers;
808     ModelSafeRoutingInfo routing_info;
809     GetModelSafeRoutingInfo(&routing_info);
810
811     // This works only because all routing info types are GROUP_PASSIVE.
812     // If we had types in other groups, we would need additional workers
813     // to support them.
814     scoped_refptr<ModelSafeWorker> worker = new FakeModelWorker(GROUP_PASSIVE);
815     workers.push_back(worker);
816
817     // Takes ownership of |fake_invalidator_|.
818     sync_manager_.Init(
819         temp_dir_.path(),
820         WeakHandle<JsEventHandler>(),
821         "bogus",
822         0,
823         false,
824         scoped_ptr<HttpPostProviderFactory>(new TestHttpPostProviderFactory()),
825         workers,
826         extensions_activity_.get(),
827         this,
828         credentials,
829         "fake_invalidator_client_id",
830         std::string(),
831         std::string(),  // bootstrap tokens
832         scoped_ptr<InternalComponentsFactory>(GetFactory()).get(),
833         &encryptor_,
834         scoped_ptr<UnrecoverableErrorHandler>(
835             new TestUnrecoverableErrorHandler).Pass(),
836         NULL,
837         &cancelation_signal_);
838
839     sync_manager_.GetEncryptionHandler()->AddObserver(&encryption_observer_);
840
841     EXPECT_TRUE(js_backend_.IsInitialized());
842
843     if (initialization_succeeded_) {
844       for (ModelSafeRoutingInfo::iterator i = routing_info.begin();
845            i != routing_info.end(); ++i) {
846         type_roots_[i->first] = MakeServerNodeForType(
847             sync_manager_.GetUserShare(), i->first);
848       }
849     }
850
851     PumpLoop();
852   }
853
854   void TearDown() {
855     sync_manager_.RemoveObserver(&manager_observer_);
856     sync_manager_.ShutdownOnSyncThread();
857     PumpLoop();
858   }
859
860   void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) {
861     (*out)[NIGORI] = GROUP_PASSIVE;
862     (*out)[DEVICE_INFO] = GROUP_PASSIVE;
863     (*out)[EXPERIMENTS] = GROUP_PASSIVE;
864     (*out)[BOOKMARKS] = GROUP_PASSIVE;
865     (*out)[THEMES] = GROUP_PASSIVE;
866     (*out)[SESSIONS] = GROUP_PASSIVE;
867     (*out)[PASSWORDS] = GROUP_PASSIVE;
868     (*out)[PREFERENCES] = GROUP_PASSIVE;
869     (*out)[PRIORITY_PREFERENCES] = GROUP_PASSIVE;
870   }
871
872   ModelTypeSet GetEnabledTypes() {
873     ModelSafeRoutingInfo routing_info;
874     GetModelSafeRoutingInfo(&routing_info);
875     return GetRoutingInfoTypes(routing_info);
876   }
877
878   virtual void OnChangesApplied(
879       ModelType model_type,
880       int64 model_version,
881       const BaseTransaction* trans,
882       const ImmutableChangeRecordList& changes) OVERRIDE {}
883
884   virtual void OnChangesComplete(ModelType model_type) OVERRIDE {}
885
886   // Helper methods.
887   bool SetUpEncryption(NigoriStatus nigori_status,
888                        EncryptionStatus encryption_status) {
889     UserShare* share = sync_manager_.GetUserShare();
890
891     // We need to create the nigori node as if it were an applied server update.
892     int64 nigori_id = GetIdForDataType(NIGORI);
893     if (nigori_id == kInvalidId)
894       return false;
895
896     // Set the nigori cryptographer information.
897     if (encryption_status == FULL_ENCRYPTION)
898       sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();
899
900     WriteTransaction trans(FROM_HERE, share);
901     Cryptographer* cryptographer = trans.GetCryptographer();
902     if (!cryptographer)
903       return false;
904     if (encryption_status != UNINITIALIZED) {
905       KeyParams params = {"localhost", "dummy", "foobar"};
906       cryptographer->AddKey(params);
907     } else {
908       DCHECK_NE(nigori_status, WRITE_TO_NIGORI);
909     }
910     if (nigori_status == WRITE_TO_NIGORI) {
911       sync_pb::NigoriSpecifics nigori;
912       cryptographer->GetKeys(nigori.mutable_encryption_keybag());
913       share->directory->GetNigoriHandler()->UpdateNigoriFromEncryptedTypes(
914           &nigori,
915           trans.GetWrappedTrans());
916       WriteNode node(&trans);
917       EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(nigori_id));
918       node.SetNigoriSpecifics(nigori);
919     }
920     return cryptographer->is_ready();
921   }
922
923   int64 GetIdForDataType(ModelType type) {
924     if (type_roots_.count(type) == 0)
925       return 0;
926     return type_roots_[type];
927   }
928
929   void PumpLoop() {
930     message_loop_.RunUntilIdle();
931   }
932
933   void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler) {
934     js_backend_.Call(FROM_HERE, &JsBackend::SetJsEventHandler,
935                      event_handler);
936     PumpLoop();
937   }
938
939   // Looks up an entry by client tag and resets IS_UNSYNCED value to false.
940   // Returns true if entry was previously unsynced, false if IS_UNSYNCED was
941   // already false.
942   bool ResetUnsyncedEntry(ModelType type,
943                           const std::string& client_tag) {
944     UserShare* share = sync_manager_.GetUserShare();
945     syncable::WriteTransaction trans(
946         FROM_HERE, syncable::UNITTEST, share->directory.get());
947     const std::string hash = syncable::GenerateSyncableHash(type, client_tag);
948     syncable::MutableEntry entry(&trans, syncable::GET_BY_CLIENT_TAG,
949                                  hash);
950     EXPECT_TRUE(entry.good());
951     if (!entry.GetIsUnsynced())
952       return false;
953     entry.PutIsUnsynced(false);
954     return true;
955   }
956
957   virtual InternalComponentsFactory* GetFactory() {
958     return new TestInternalComponentsFactory(GetSwitches(), STORAGE_IN_MEMORY);
959   }
960
961   // Returns true if we are currently encrypting all sync data.  May
962   // be called on any thread.
963   bool EncryptEverythingEnabledForTest() {
964     return sync_manager_.GetEncryptionHandler()->EncryptEverythingEnabled();
965   }
966
967   // Gets the set of encrypted types from the cryptographer
968   // Note: opens a transaction.  May be called from any thread.
969   ModelTypeSet GetEncryptedTypes() {
970     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
971     return GetEncryptedTypesWithTrans(&trans);
972   }
973
974   ModelTypeSet GetEncryptedTypesWithTrans(BaseTransaction* trans) {
975     return trans->GetDirectory()->GetNigoriHandler()->
976         GetEncryptedTypes(trans->GetWrappedTrans());
977   }
978
979   void SimulateInvalidatorStateChangeForTest(InvalidatorState state) {
980     DCHECK(sync_manager_.thread_checker_.CalledOnValidThread());
981     sync_manager_.OnInvalidatorStateChange(state);
982   }
983
984   void TriggerOnIncomingNotificationForTest(ModelTypeSet model_types) {
985     DCHECK(sync_manager_.thread_checker_.CalledOnValidThread());
986     ObjectIdSet id_set = ModelTypeSetToObjectIdSet(model_types);
987     ObjectIdInvalidationMap invalidation_map =
988         ObjectIdInvalidationMap::InvalidateAll(id_set);
989     sync_manager_.OnIncomingInvalidation(invalidation_map);
990   }
991
992   void SetProgressMarkerForType(ModelType type, bool set) {
993     if (set) {
994       sync_pb::DataTypeProgressMarker marker;
995       marker.set_token("token");
996       marker.set_data_type_id(GetSpecificsFieldNumberFromModelType(type));
997       sync_manager_.directory()->SetDownloadProgress(type, marker);
998     } else {
999       sync_pb::DataTypeProgressMarker marker;
1000       sync_manager_.directory()->SetDownloadProgress(type, marker);
1001     }
1002   }
1003
1004   InternalComponentsFactory::Switches GetSwitches() const {
1005     return switches_;
1006   }
1007
1008  private:
1009   // Needed by |sync_manager_|.
1010   base::MessageLoop message_loop_;
1011   // Needed by |sync_manager_|.
1012   base::ScopedTempDir temp_dir_;
1013   // Sync Id's for the roots of the enabled datatypes.
1014   std::map<ModelType, int64> type_roots_;
1015   scoped_refptr<ExtensionsActivity> extensions_activity_;
1016
1017  protected:
1018   FakeEncryptor encryptor_;
1019   SyncManagerImpl sync_manager_;
1020   CancelationSignal cancelation_signal_;
1021   WeakHandle<JsBackend> js_backend_;
1022   bool initialization_succeeded_;
1023   StrictMock<SyncManagerObserverMock> manager_observer_;
1024   StrictMock<SyncEncryptionHandlerObserverMock> encryption_observer_;
1025   InternalComponentsFactory::Switches switches_;
1026 };
1027
1028 TEST_F(SyncManagerTest, GetAllNodesForTypeTest) {
1029   ModelSafeRoutingInfo routing_info;
1030   GetModelSafeRoutingInfo(&routing_info);
1031   sync_manager_.StartSyncingNormally(routing_info);
1032
1033   scoped_ptr<base::ListValue> node_list(
1034       sync_manager_.GetAllNodesForType(syncer::PREFERENCES));
1035
1036   // Should have one node: the type root node.
1037   ASSERT_EQ(1U, node_list->GetSize());
1038
1039   const base::DictionaryValue* first_result;
1040   ASSERT_TRUE(node_list->GetDictionary(0, &first_result));
1041   EXPECT_TRUE(first_result->HasKey("ID"));
1042   EXPECT_TRUE(first_result->HasKey("NON_UNIQUE_NAME"));
1043 }
1044
1045 TEST_F(SyncManagerTest, RefreshEncryptionReady) {
1046   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1047   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1048   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1049   EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));
1050
1051   sync_manager_.GetEncryptionHandler()->Init();
1052   PumpLoop();
1053
1054   const ModelTypeSet encrypted_types = GetEncryptedTypes();
1055   EXPECT_TRUE(encrypted_types.Has(PASSWORDS));
1056   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1057
1058   {
1059     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1060     ReadNode node(&trans);
1061     EXPECT_EQ(BaseNode::INIT_OK,
1062               node.InitByIdLookup(GetIdForDataType(NIGORI)));
1063     sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics();
1064     EXPECT_TRUE(nigori.has_encryption_keybag());
1065     Cryptographer* cryptographer = trans.GetCryptographer();
1066     EXPECT_TRUE(cryptographer->is_ready());
1067     EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encryption_keybag()));
1068   }
1069 }
1070
1071 // Attempt to refresh encryption when nigori not downloaded.
1072 TEST_F(SyncManagerTest, RefreshEncryptionNotReady) {
1073   // Don't set up encryption (no nigori node created).
1074
1075   // Should fail. Triggers an OnPassphraseRequired because the cryptographer
1076   // is not ready.
1077   EXPECT_CALL(encryption_observer_, OnPassphraseRequired(_, _)).Times(1);
1078   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1079   EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));
1080   sync_manager_.GetEncryptionHandler()->Init();
1081   PumpLoop();
1082
1083   const ModelTypeSet encrypted_types = GetEncryptedTypes();
1084   EXPECT_TRUE(encrypted_types.Has(PASSWORDS));  // Hardcoded.
1085   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1086 }
1087
1088 // Attempt to refresh encryption when nigori is empty.
1089 TEST_F(SyncManagerTest, RefreshEncryptionEmptyNigori) {
1090   EXPECT_TRUE(SetUpEncryption(DONT_WRITE_NIGORI, DEFAULT_ENCRYPTION));
1091   EXPECT_CALL(encryption_observer_, OnEncryptionComplete()).Times(1);
1092   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1093   EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));
1094
1095   // Should write to nigori.
1096   sync_manager_.GetEncryptionHandler()->Init();
1097   PumpLoop();
1098
1099   const ModelTypeSet encrypted_types = GetEncryptedTypes();
1100   EXPECT_TRUE(encrypted_types.Has(PASSWORDS));  // Hardcoded.
1101   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1102
1103   {
1104     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1105     ReadNode node(&trans);
1106     EXPECT_EQ(BaseNode::INIT_OK,
1107               node.InitByIdLookup(GetIdForDataType(NIGORI)));
1108     sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics();
1109     EXPECT_TRUE(nigori.has_encryption_keybag());
1110     Cryptographer* cryptographer = trans.GetCryptographer();
1111     EXPECT_TRUE(cryptographer->is_ready());
1112     EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encryption_keybag()));
1113   }
1114 }
1115
1116 TEST_F(SyncManagerTest, EncryptDataTypesWithNoData) {
1117   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1118   EXPECT_CALL(encryption_observer_,
1119               OnEncryptedTypesChanged(
1120                   HasModelTypes(EncryptableUserTypes()), true));
1121   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1122   sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();
1123   EXPECT_TRUE(EncryptEverythingEnabledForTest());
1124 }
1125
1126 TEST_F(SyncManagerTest, EncryptDataTypesWithData) {
1127   size_t batch_size = 5;
1128   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1129
1130   // Create some unencrypted unsynced data.
1131   int64 folder = MakeFolderWithParent(sync_manager_.GetUserShare(),
1132                                       BOOKMARKS,
1133                                       GetIdForDataType(BOOKMARKS),
1134                                       NULL);
1135   // First batch_size nodes are children of folder.
1136   size_t i;
1137   for (i = 0; i < batch_size; ++i) {
1138     MakeBookmarkWithParent(sync_manager_.GetUserShare(), folder, NULL);
1139   }
1140   // Next batch_size nodes are a different type and on their own.
1141   for (; i < 2*batch_size; ++i) {
1142     MakeNode(sync_manager_.GetUserShare(), SESSIONS,
1143              base::StringPrintf("%" PRIuS "", i));
1144   }
1145   // Last batch_size nodes are a third type that will not need encryption.
1146   for (; i < 3*batch_size; ++i) {
1147     MakeNode(sync_manager_.GetUserShare(), THEMES,
1148              base::StringPrintf("%" PRIuS "", i));
1149   }
1150
1151   {
1152     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1153     EXPECT_TRUE(GetEncryptedTypesWithTrans(&trans).Equals(
1154         SyncEncryptionHandler::SensitiveTypes()));
1155     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1156         trans.GetWrappedTrans(),
1157         BOOKMARKS,
1158         false /* not encrypted */));
1159     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1160         trans.GetWrappedTrans(),
1161         SESSIONS,
1162         false /* not encrypted */));
1163     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1164         trans.GetWrappedTrans(),
1165         THEMES,
1166         false /* not encrypted */));
1167   }
1168
1169   EXPECT_CALL(encryption_observer_,
1170               OnEncryptedTypesChanged(
1171                   HasModelTypes(EncryptableUserTypes()), true));
1172   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1173   sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();
1174   EXPECT_TRUE(EncryptEverythingEnabledForTest());
1175   {
1176     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1177     EXPECT_TRUE(GetEncryptedTypesWithTrans(&trans).Equals(
1178         EncryptableUserTypes()));
1179     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1180         trans.GetWrappedTrans(),
1181         BOOKMARKS,
1182         true /* is encrypted */));
1183     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1184         trans.GetWrappedTrans(),
1185         SESSIONS,
1186         true /* is encrypted */));
1187     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1188         trans.GetWrappedTrans(),
1189         THEMES,
1190         true /* is encrypted */));
1191   }
1192
1193   // Trigger's a ReEncryptEverything with new passphrase.
1194   testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
1195   EXPECT_CALL(encryption_observer_,
1196               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1197   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1198   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1199   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1200   EXPECT_CALL(encryption_observer_,
1201               OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
1202   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
1203       "new_passphrase", true);
1204   EXPECT_TRUE(EncryptEverythingEnabledForTest());
1205   {
1206     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1207     EXPECT_TRUE(GetEncryptedTypesWithTrans(&trans).Equals(
1208         EncryptableUserTypes()));
1209     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1210         trans.GetWrappedTrans(),
1211         BOOKMARKS,
1212         true /* is encrypted */));
1213     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1214         trans.GetWrappedTrans(),
1215         SESSIONS,
1216         true /* is encrypted */));
1217     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1218         trans.GetWrappedTrans(),
1219         THEMES,
1220         true /* is encrypted */));
1221   }
1222   // Calling EncryptDataTypes with an empty encrypted types should not trigger
1223   // a reencryption and should just notify immediately.
1224   testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
1225   EXPECT_CALL(encryption_observer_,
1226               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN)).Times(0);
1227   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted()).Times(0);
1228   EXPECT_CALL(encryption_observer_, OnEncryptionComplete()).Times(0);
1229   sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();
1230 }
1231
1232 // Test that when there are no pending keys and the cryptographer is not
1233 // initialized, we add a key based on the current GAIA password.
1234 // (case 1 in SyncManager::SyncInternal::SetEncryptionPassphrase)
1235 TEST_F(SyncManagerTest, SetInitialGaiaPass) {
1236   EXPECT_FALSE(SetUpEncryption(DONT_WRITE_NIGORI, UNINITIALIZED));
1237   EXPECT_CALL(encryption_observer_,
1238               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1239   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1240   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1241   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1242   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
1243       "new_passphrase",
1244       false);
1245   EXPECT_EQ(IMPLICIT_PASSPHRASE,
1246             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
1247   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1248   {
1249     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1250     ReadNode node(&trans);
1251     EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag));
1252     sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics();
1253     Cryptographer* cryptographer = trans.GetCryptographer();
1254     EXPECT_TRUE(cryptographer->is_ready());
1255     EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encryption_keybag()));
1256   }
1257 }
1258
1259 // Test that when there are no pending keys and we have on the old GAIA
1260 // password, we update and re-encrypt everything with the new GAIA password.
1261 // (case 1 in SyncManager::SyncInternal::SetEncryptionPassphrase)
1262 TEST_F(SyncManagerTest, UpdateGaiaPass) {
1263   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1264   Cryptographer verifier(&encryptor_);
1265   {
1266     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1267     Cryptographer* cryptographer = trans.GetCryptographer();
1268     std::string bootstrap_token;
1269     cryptographer->GetBootstrapToken(&bootstrap_token);
1270     verifier.Bootstrap(bootstrap_token);
1271   }
1272   EXPECT_CALL(encryption_observer_,
1273               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1274   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1275   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1276   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1277   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
1278       "new_passphrase",
1279       false);
1280   EXPECT_EQ(IMPLICIT_PASSPHRASE,
1281             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
1282   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1283   {
1284     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1285     Cryptographer* cryptographer = trans.GetCryptographer();
1286     EXPECT_TRUE(cryptographer->is_ready());
1287     // Verify the default key has changed.
1288     sync_pb::EncryptedData encrypted;
1289     cryptographer->GetKeys(&encrypted);
1290     EXPECT_FALSE(verifier.CanDecrypt(encrypted));
1291   }
1292 }
1293
1294 // Sets a new explicit passphrase. This should update the bootstrap token
1295 // and re-encrypt everything.
1296 // (case 2 in SyncManager::SyncInternal::SetEncryptionPassphrase)
1297 TEST_F(SyncManagerTest, SetPassphraseWithPassword) {
1298   Cryptographer verifier(&encryptor_);
1299   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1300   {
1301     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1302     // Store the default (soon to be old) key.
1303     Cryptographer* cryptographer = trans.GetCryptographer();
1304     std::string bootstrap_token;
1305     cryptographer->GetBootstrapToken(&bootstrap_token);
1306     verifier.Bootstrap(bootstrap_token);
1307
1308     ReadNode root_node(&trans);
1309     root_node.InitByRootLookup();
1310
1311     WriteNode password_node(&trans);
1312     WriteNode::InitUniqueByCreationResult result =
1313         password_node.InitUniqueByCreation(PASSWORDS,
1314                                            root_node, "foo");
1315     EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
1316     sync_pb::PasswordSpecificsData data;
1317     data.set_password_value("secret");
1318     password_node.SetPasswordSpecifics(data);
1319   }
1320     EXPECT_CALL(encryption_observer_,
1321               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1322   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1323   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1324   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1325   EXPECT_CALL(encryption_observer_,
1326       OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
1327   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
1328       "new_passphrase",
1329       true);
1330   EXPECT_EQ(CUSTOM_PASSPHRASE,
1331             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
1332   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1333   {
1334     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1335     Cryptographer* cryptographer = trans.GetCryptographer();
1336     EXPECT_TRUE(cryptographer->is_ready());
1337     // Verify the default key has changed.
1338     sync_pb::EncryptedData encrypted;
1339     cryptographer->GetKeys(&encrypted);
1340     EXPECT_FALSE(verifier.CanDecrypt(encrypted));
1341
1342     ReadNode password_node(&trans);
1343     EXPECT_EQ(BaseNode::INIT_OK,
1344               password_node.InitByClientTagLookup(PASSWORDS,
1345                                                   "foo"));
1346     const sync_pb::PasswordSpecificsData& data =
1347         password_node.GetPasswordSpecifics();
1348     EXPECT_EQ("secret", data.password_value());
1349   }
1350 }
1351
1352 // Manually set the pending keys in the cryptographer/nigori to reflect the data
1353 // being encrypted with a new (unprovided) GAIA password, then supply the
1354 // password.
1355 // (case 7 in SyncManager::SyncInternal::SetDecryptionPassphrase)
1356 TEST_F(SyncManagerTest, SupplyPendingGAIAPass) {
1357   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1358   Cryptographer other_cryptographer(&encryptor_);
1359   {
1360     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1361     Cryptographer* cryptographer = trans.GetCryptographer();
1362     std::string bootstrap_token;
1363     cryptographer->GetBootstrapToken(&bootstrap_token);
1364     other_cryptographer.Bootstrap(bootstrap_token);
1365
1366     // Now update the nigori to reflect the new keys, and update the
1367     // cryptographer to have pending keys.
1368     KeyParams params = {"localhost", "dummy", "passphrase2"};
1369     other_cryptographer.AddKey(params);
1370     WriteNode node(&trans);
1371     EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag));
1372     sync_pb::NigoriSpecifics nigori;
1373     other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
1374     cryptographer->SetPendingKeys(nigori.encryption_keybag());
1375     EXPECT_TRUE(cryptographer->has_pending_keys());
1376     node.SetNigoriSpecifics(nigori);
1377   }
1378   EXPECT_CALL(encryption_observer_,
1379               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1380   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1381   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1382   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1383   sync_manager_.GetEncryptionHandler()->SetDecryptionPassphrase("passphrase2");
1384   EXPECT_EQ(IMPLICIT_PASSPHRASE,
1385             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
1386   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1387   {
1388     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1389     Cryptographer* cryptographer = trans.GetCryptographer();
1390     EXPECT_TRUE(cryptographer->is_ready());
1391     // Verify we're encrypting with the new key.
1392     sync_pb::EncryptedData encrypted;
1393     cryptographer->GetKeys(&encrypted);
1394     EXPECT_TRUE(other_cryptographer.CanDecrypt(encrypted));
1395   }
1396 }
1397
1398 // Manually set the pending keys in the cryptographer/nigori to reflect the data
1399 // being encrypted with an old (unprovided) GAIA password. Attempt to supply
1400 // the current GAIA password and verify the bootstrap token is updated. Then
1401 // supply the old GAIA password, and verify we re-encrypt all data with the
1402 // new GAIA password.
1403 // (cases 4 and 5 in SyncManager::SyncInternal::SetEncryptionPassphrase)
1404 TEST_F(SyncManagerTest, SupplyPendingOldGAIAPass) {
1405   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1406   Cryptographer other_cryptographer(&encryptor_);
1407   {
1408     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1409     Cryptographer* cryptographer = trans.GetCryptographer();
1410     std::string bootstrap_token;
1411     cryptographer->GetBootstrapToken(&bootstrap_token);
1412     other_cryptographer.Bootstrap(bootstrap_token);
1413
1414     // Now update the nigori to reflect the new keys, and update the
1415     // cryptographer to have pending keys.
1416     KeyParams params = {"localhost", "dummy", "old_gaia"};
1417     other_cryptographer.AddKey(params);
1418     WriteNode node(&trans);
1419     EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag));
1420     sync_pb::NigoriSpecifics nigori;
1421     other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
1422     node.SetNigoriSpecifics(nigori);
1423     cryptographer->SetPendingKeys(nigori.encryption_keybag());
1424
1425     // other_cryptographer now contains all encryption keys, and is encrypting
1426     // with the newest gaia.
1427     KeyParams new_params = {"localhost", "dummy", "new_gaia"};
1428     other_cryptographer.AddKey(new_params);
1429   }
1430   // The bootstrap token should have been updated. Save it to ensure it's based
1431   // on the new GAIA password.
1432   std::string bootstrap_token;
1433   EXPECT_CALL(encryption_observer_,
1434               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN))
1435       .WillOnce(SaveArg<0>(&bootstrap_token));
1436   EXPECT_CALL(encryption_observer_, OnPassphraseRequired(_,_));
1437   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1438   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
1439       "new_gaia",
1440       false);
1441   EXPECT_EQ(IMPLICIT_PASSPHRASE,
1442             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
1443   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1444   testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
1445   {
1446     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1447     Cryptographer* cryptographer = trans.GetCryptographer();
1448     EXPECT_TRUE(cryptographer->is_initialized());
1449     EXPECT_FALSE(cryptographer->is_ready());
1450     // Verify we're encrypting with the new key, even though we have pending
1451     // keys.
1452     sync_pb::EncryptedData encrypted;
1453     other_cryptographer.GetKeys(&encrypted);
1454     EXPECT_TRUE(cryptographer->CanDecrypt(encrypted));
1455   }
1456   EXPECT_CALL(encryption_observer_,
1457               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1458   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1459   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1460   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1461   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
1462       "old_gaia",
1463       false);
1464   EXPECT_EQ(IMPLICIT_PASSPHRASE,
1465             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
1466   {
1467     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1468     Cryptographer* cryptographer = trans.GetCryptographer();
1469     EXPECT_TRUE(cryptographer->is_ready());
1470
1471     // Verify we're encrypting with the new key.
1472     sync_pb::EncryptedData encrypted;
1473     other_cryptographer.GetKeys(&encrypted);
1474     EXPECT_TRUE(cryptographer->CanDecrypt(encrypted));
1475
1476     // Verify the saved bootstrap token is based on the new gaia password.
1477     Cryptographer temp_cryptographer(&encryptor_);
1478     temp_cryptographer.Bootstrap(bootstrap_token);
1479     EXPECT_TRUE(temp_cryptographer.CanDecrypt(encrypted));
1480   }
1481 }
1482
1483 // Manually set the pending keys in the cryptographer/nigori to reflect the data
1484 // being encrypted with an explicit (unprovided) passphrase, then supply the
1485 // passphrase.
1486 // (case 9 in SyncManager::SyncInternal::SetDecryptionPassphrase)
1487 TEST_F(SyncManagerTest, SupplyPendingExplicitPass) {
1488   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1489   Cryptographer other_cryptographer(&encryptor_);
1490   {
1491     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1492     Cryptographer* cryptographer = trans.GetCryptographer();
1493     std::string bootstrap_token;
1494     cryptographer->GetBootstrapToken(&bootstrap_token);
1495     other_cryptographer.Bootstrap(bootstrap_token);
1496
1497     // Now update the nigori to reflect the new keys, and update the
1498     // cryptographer to have pending keys.
1499     KeyParams params = {"localhost", "dummy", "explicit"};
1500     other_cryptographer.AddKey(params);
1501     WriteNode node(&trans);
1502     EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag));
1503     sync_pb::NigoriSpecifics nigori;
1504     other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
1505     cryptographer->SetPendingKeys(nigori.encryption_keybag());
1506     EXPECT_TRUE(cryptographer->has_pending_keys());
1507     nigori.set_keybag_is_frozen(true);
1508     node.SetNigoriSpecifics(nigori);
1509   }
1510   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1511   EXPECT_CALL(encryption_observer_,
1512               OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
1513   EXPECT_CALL(encryption_observer_, OnPassphraseRequired(_, _));
1514   EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));
1515   sync_manager_.GetEncryptionHandler()->Init();
1516   EXPECT_CALL(encryption_observer_,
1517               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1518   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1519   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1520   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1521   sync_manager_.GetEncryptionHandler()->SetDecryptionPassphrase("explicit");
1522   EXPECT_EQ(CUSTOM_PASSPHRASE,
1523             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
1524   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1525   {
1526     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1527     Cryptographer* cryptographer = trans.GetCryptographer();
1528     EXPECT_TRUE(cryptographer->is_ready());
1529     // Verify we're encrypting with the new key.
1530     sync_pb::EncryptedData encrypted;
1531     cryptographer->GetKeys(&encrypted);
1532     EXPECT_TRUE(other_cryptographer.CanDecrypt(encrypted));
1533   }
1534 }
1535
1536 // Manually set the pending keys in the cryptographer/nigori to reflect the data
1537 // being encrypted with a new (unprovided) GAIA password, then supply the
1538 // password as a user-provided password.
1539 // This is the android case 7/8.
1540 TEST_F(SyncManagerTest, SupplyPendingGAIAPassUserProvided) {
1541   EXPECT_FALSE(SetUpEncryption(DONT_WRITE_NIGORI, UNINITIALIZED));
1542   Cryptographer other_cryptographer(&encryptor_);
1543   {
1544     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1545     Cryptographer* cryptographer = trans.GetCryptographer();
1546     // Now update the nigori to reflect the new keys, and update the
1547     // cryptographer to have pending keys.
1548     KeyParams params = {"localhost", "dummy", "passphrase"};
1549     other_cryptographer.AddKey(params);
1550     WriteNode node(&trans);
1551     EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag));
1552     sync_pb::NigoriSpecifics nigori;
1553     other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
1554     node.SetNigoriSpecifics(nigori);
1555     cryptographer->SetPendingKeys(nigori.encryption_keybag());
1556     EXPECT_FALSE(cryptographer->is_ready());
1557   }
1558   EXPECT_CALL(encryption_observer_,
1559               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1560   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1561   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1562   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1563   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
1564       "passphrase",
1565       false);
1566   EXPECT_EQ(IMPLICIT_PASSPHRASE,
1567             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
1568   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1569   {
1570     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1571     Cryptographer* cryptographer = trans.GetCryptographer();
1572     EXPECT_TRUE(cryptographer->is_ready());
1573   }
1574 }
1575
1576 TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) {
1577   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1578   int64 node_id = 0;
1579   std::string tag = "foo";
1580   {
1581     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1582     ReadNode root_node(&trans);
1583     root_node.InitByRootLookup();
1584
1585     WriteNode password_node(&trans);
1586     WriteNode::InitUniqueByCreationResult result =
1587         password_node.InitUniqueByCreation(PASSWORDS, root_node, tag);
1588     EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
1589     node_id = password_node.GetId();
1590   }
1591   EXPECT_CALL(encryption_observer_,
1592               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1593   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1594   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1595   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1596   EXPECT_CALL(encryption_observer_,
1597       OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
1598   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
1599       "new_passphrase",
1600       true);
1601   EXPECT_EQ(CUSTOM_PASSPHRASE,
1602             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
1603   EXPECT_FALSE(EncryptEverythingEnabledForTest());
1604   {
1605     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1606     ReadNode password_node(&trans);
1607     EXPECT_EQ(BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY,
1608               password_node.InitByClientTagLookup(PASSWORDS,
1609                                                   tag));
1610   }
1611   {
1612     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1613     ReadNode password_node(&trans);
1614     EXPECT_EQ(BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY,
1615               password_node.InitByIdLookup(node_id));
1616   }
1617 }
1618
1619 TEST_F(SyncManagerTest, NudgeDelayTest) {
1620   EXPECT_EQ(sync_manager_.GetNudgeDelayTimeDelta(BOOKMARKS),
1621       base::TimeDelta::FromMilliseconds(
1622           SyncManagerImpl::GetDefaultNudgeDelay()));
1623
1624   EXPECT_EQ(sync_manager_.GetNudgeDelayTimeDelta(AUTOFILL),
1625       base::TimeDelta::FromSeconds(
1626           kDefaultShortPollIntervalSeconds));
1627
1628   EXPECT_EQ(sync_manager_.GetNudgeDelayTimeDelta(PREFERENCES),
1629       base::TimeDelta::FromMilliseconds(
1630           SyncManagerImpl::GetPreferencesNudgeDelay()));
1631 }
1632
1633 // Friended by WriteNode, so can't be in an anonymouse namespace.
1634 TEST_F(SyncManagerTest, EncryptBookmarksWithLegacyData) {
1635   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1636   std::string title;
1637   SyncAPINameToServerName("Google", &title);
1638   std::string url = "http://www.google.com";
1639   std::string raw_title2 = "..";  // An invalid cosmo title.
1640   std::string title2;
1641   SyncAPINameToServerName(raw_title2, &title2);
1642   std::string url2 = "http://www.bla.com";
1643
1644   // Create a bookmark using the legacy format.
1645   int64 node_id1 = MakeNode(sync_manager_.GetUserShare(),
1646       BOOKMARKS,
1647       "testtag");
1648   int64 node_id2 = MakeNode(sync_manager_.GetUserShare(),
1649       BOOKMARKS,
1650       "testtag2");
1651   {
1652     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1653     WriteNode node(&trans);
1654     EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(node_id1));
1655
1656     sync_pb::EntitySpecifics entity_specifics;
1657     entity_specifics.mutable_bookmark()->set_url(url);
1658     node.SetEntitySpecifics(entity_specifics);
1659
1660     // Set the old style title.
1661     syncable::MutableEntry* node_entry = node.entry_;
1662     node_entry->PutNonUniqueName(title);
1663
1664     WriteNode node2(&trans);
1665     EXPECT_EQ(BaseNode::INIT_OK, node2.InitByIdLookup(node_id2));
1666
1667     sync_pb::EntitySpecifics entity_specifics2;
1668     entity_specifics2.mutable_bookmark()->set_url(url2);
1669     node2.SetEntitySpecifics(entity_specifics2);
1670
1671     // Set the old style title.
1672     syncable::MutableEntry* node_entry2 = node2.entry_;
1673     node_entry2->PutNonUniqueName(title2);
1674   }
1675
1676   {
1677     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1678     ReadNode node(&trans);
1679     EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(node_id1));
1680     EXPECT_EQ(BOOKMARKS, node.GetModelType());
1681     EXPECT_EQ(title, node.GetTitle());
1682     EXPECT_EQ(title, node.GetBookmarkSpecifics().title());
1683     EXPECT_EQ(url, node.GetBookmarkSpecifics().url());
1684
1685     ReadNode node2(&trans);
1686     EXPECT_EQ(BaseNode::INIT_OK, node2.InitByIdLookup(node_id2));
1687     EXPECT_EQ(BOOKMARKS, node2.GetModelType());
1688     // We should de-canonicalize the title in GetTitle(), but the title in the
1689     // specifics should be stored in the server legal form.
1690     EXPECT_EQ(raw_title2, node2.GetTitle());
1691     EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title());
1692     EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url());
1693   }
1694
1695   {
1696     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1697     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1698         trans.GetWrappedTrans(),
1699         BOOKMARKS,
1700         false /* not encrypted */));
1701   }
1702
1703   EXPECT_CALL(encryption_observer_,
1704               OnEncryptedTypesChanged(
1705                   HasModelTypes(EncryptableUserTypes()), true));
1706   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1707   sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();
1708   EXPECT_TRUE(EncryptEverythingEnabledForTest());
1709
1710   {
1711     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1712     EXPECT_TRUE(GetEncryptedTypesWithTrans(&trans).Equals(
1713         EncryptableUserTypes()));
1714     EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
1715         trans.GetWrappedTrans(),
1716         BOOKMARKS,
1717         true /* is encrypted */));
1718
1719     ReadNode node(&trans);
1720     EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(node_id1));
1721     EXPECT_EQ(BOOKMARKS, node.GetModelType());
1722     EXPECT_EQ(title, node.GetTitle());
1723     EXPECT_EQ(title, node.GetBookmarkSpecifics().title());
1724     EXPECT_EQ(url, node.GetBookmarkSpecifics().url());
1725
1726     ReadNode node2(&trans);
1727     EXPECT_EQ(BaseNode::INIT_OK, node2.InitByIdLookup(node_id2));
1728     EXPECT_EQ(BOOKMARKS, node2.GetModelType());
1729     // We should de-canonicalize the title in GetTitle(), but the title in the
1730     // specifics should be stored in the server legal form.
1731     EXPECT_EQ(raw_title2, node2.GetTitle());
1732     EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title());
1733     EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url());
1734   }
1735 }
1736
1737 // Create a bookmark and set the title/url, then verify the data was properly
1738 // set. This replicates the unique way bookmarks have of creating sync nodes.
1739 // See BookmarkChangeProcessor::PlaceSyncNode(..).
1740 TEST_F(SyncManagerTest, CreateLocalBookmark) {
1741   std::string title = "title";
1742   std::string url = "url";
1743   {
1744     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1745     ReadNode bookmark_root(&trans);
1746     ASSERT_EQ(BaseNode::INIT_OK,
1747               bookmark_root.InitByTagLookup(ModelTypeToRootTag(BOOKMARKS)));
1748     WriteNode node(&trans);
1749     ASSERT_TRUE(node.InitBookmarkByCreation(bookmark_root, NULL));
1750     node.SetIsFolder(false);
1751     node.SetTitle(title);
1752
1753     sync_pb::BookmarkSpecifics bookmark_specifics(node.GetBookmarkSpecifics());
1754     bookmark_specifics.set_url(url);
1755     node.SetBookmarkSpecifics(bookmark_specifics);
1756   }
1757   {
1758     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1759     ReadNode bookmark_root(&trans);
1760     ASSERT_EQ(BaseNode::INIT_OK,
1761               bookmark_root.InitByTagLookup(ModelTypeToRootTag(BOOKMARKS)));
1762     int64 child_id = bookmark_root.GetFirstChildId();
1763
1764     ReadNode node(&trans);
1765     ASSERT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(child_id));
1766     EXPECT_FALSE(node.GetIsFolder());
1767     EXPECT_EQ(title, node.GetTitle());
1768     EXPECT_EQ(url, node.GetBookmarkSpecifics().url());
1769   }
1770 }
1771
1772 // Verifies WriteNode::UpdateEntryWithEncryption does not make unnecessary
1773 // changes.
1774 TEST_F(SyncManagerTest, UpdateEntryWithEncryption) {
1775   std::string client_tag = "title";
1776   sync_pb::EntitySpecifics entity_specifics;
1777   entity_specifics.mutable_bookmark()->set_url("url");
1778   entity_specifics.mutable_bookmark()->set_title("title");
1779   MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
1780                  syncable::GenerateSyncableHash(BOOKMARKS,
1781                                                 client_tag),
1782                  entity_specifics);
1783   // New node shouldn't start off unsynced.
1784   EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
1785   // Manually change to the same data. Should not set is_unsynced.
1786   {
1787     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1788     WriteNode node(&trans);
1789     EXPECT_EQ(BaseNode::INIT_OK,
1790               node.InitByClientTagLookup(BOOKMARKS, client_tag));
1791     node.SetEntitySpecifics(entity_specifics);
1792   }
1793   EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
1794
1795   // Encrypt the datatatype, should set is_unsynced.
1796   EXPECT_CALL(encryption_observer_,
1797               OnEncryptedTypesChanged(
1798                   HasModelTypes(EncryptableUserTypes()), true));
1799   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1800   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION));
1801
1802   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1803   EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, true));
1804   sync_manager_.GetEncryptionHandler()->Init();
1805   PumpLoop();
1806   {
1807     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1808     ReadNode node(&trans);
1809     EXPECT_EQ(BaseNode::INIT_OK,
1810               node.InitByClientTagLookup(BOOKMARKS, client_tag));
1811     const syncable::Entry* node_entry = node.GetEntry();
1812     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
1813     EXPECT_TRUE(specifics.has_encrypted());
1814     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
1815     Cryptographer* cryptographer = trans.GetCryptographer();
1816     EXPECT_TRUE(cryptographer->is_ready());
1817     EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
1818         specifics.encrypted()));
1819   }
1820   EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
1821
1822   // Set a new passphrase. Should set is_unsynced.
1823   testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
1824   EXPECT_CALL(encryption_observer_,
1825               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
1826   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
1827   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1828   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1829   EXPECT_CALL(encryption_observer_,
1830       OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
1831   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
1832       "new_passphrase",
1833       true);
1834   {
1835     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1836     ReadNode node(&trans);
1837     EXPECT_EQ(BaseNode::INIT_OK,
1838               node.InitByClientTagLookup(BOOKMARKS, client_tag));
1839     const syncable::Entry* node_entry = node.GetEntry();
1840     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
1841     EXPECT_TRUE(specifics.has_encrypted());
1842     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
1843     Cryptographer* cryptographer = trans.GetCryptographer();
1844     EXPECT_TRUE(cryptographer->is_ready());
1845     EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
1846         specifics.encrypted()));
1847   }
1848   EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
1849
1850   // Force a re-encrypt everything. Should not set is_unsynced.
1851   testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
1852   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
1853   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
1854   EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, true));
1855
1856   sync_manager_.GetEncryptionHandler()->Init();
1857   PumpLoop();
1858
1859   {
1860     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1861     ReadNode node(&trans);
1862     EXPECT_EQ(BaseNode::INIT_OK,
1863               node.InitByClientTagLookup(BOOKMARKS, client_tag));
1864     const syncable::Entry* node_entry = node.GetEntry();
1865     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
1866     EXPECT_TRUE(specifics.has_encrypted());
1867     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
1868     Cryptographer* cryptographer = trans.GetCryptographer();
1869     EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
1870         specifics.encrypted()));
1871   }
1872   EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
1873
1874   // Manually change to the same data. Should not set is_unsynced.
1875   {
1876     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1877     WriteNode node(&trans);
1878     EXPECT_EQ(BaseNode::INIT_OK,
1879               node.InitByClientTagLookup(BOOKMARKS, client_tag));
1880     node.SetEntitySpecifics(entity_specifics);
1881     const syncable::Entry* node_entry = node.GetEntry();
1882     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
1883     EXPECT_TRUE(specifics.has_encrypted());
1884     EXPECT_FALSE(node_entry->GetIsUnsynced());
1885     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
1886     Cryptographer* cryptographer = trans.GetCryptographer();
1887     EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
1888         specifics.encrypted()));
1889   }
1890   EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
1891
1892   // Manually change to different data. Should set is_unsynced.
1893   {
1894     entity_specifics.mutable_bookmark()->set_url("url2");
1895     entity_specifics.mutable_bookmark()->set_title("title2");
1896     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1897     WriteNode node(&trans);
1898     EXPECT_EQ(BaseNode::INIT_OK,
1899               node.InitByClientTagLookup(BOOKMARKS, client_tag));
1900     node.SetEntitySpecifics(entity_specifics);
1901     const syncable::Entry* node_entry = node.GetEntry();
1902     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
1903     EXPECT_TRUE(specifics.has_encrypted());
1904     EXPECT_TRUE(node_entry->GetIsUnsynced());
1905     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
1906     Cryptographer* cryptographer = trans.GetCryptographer();
1907     EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
1908                     specifics.encrypted()));
1909   }
1910 }
1911
1912 // Passwords have their own handling for encryption. Verify it does not result
1913 // in unnecessary writes via SetEntitySpecifics.
1914 TEST_F(SyncManagerTest, UpdatePasswordSetEntitySpecificsNoChange) {
1915   std::string client_tag = "title";
1916   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1917   sync_pb::EntitySpecifics entity_specifics;
1918   {
1919     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1920     Cryptographer* cryptographer = trans.GetCryptographer();
1921     sync_pb::PasswordSpecificsData data;
1922     data.set_password_value("secret");
1923     cryptographer->Encrypt(
1924         data,
1925         entity_specifics.mutable_password()->
1926             mutable_encrypted());
1927   }
1928   MakeServerNode(sync_manager_.GetUserShare(), PASSWORDS, client_tag,
1929                  syncable::GenerateSyncableHash(PASSWORDS,
1930                                                 client_tag),
1931                  entity_specifics);
1932   // New node shouldn't start off unsynced.
1933   EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));
1934
1935   // Manually change to the same data via SetEntitySpecifics. Should not set
1936   // is_unsynced.
1937   {
1938     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1939     WriteNode node(&trans);
1940     EXPECT_EQ(BaseNode::INIT_OK,
1941               node.InitByClientTagLookup(PASSWORDS, client_tag));
1942     node.SetEntitySpecifics(entity_specifics);
1943   }
1944   EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));
1945 }
1946
1947 // Passwords have their own handling for encryption. Verify it does not result
1948 // in unnecessary writes via SetPasswordSpecifics.
1949 TEST_F(SyncManagerTest, UpdatePasswordSetPasswordSpecifics) {
1950   std::string client_tag = "title";
1951   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
1952   sync_pb::EntitySpecifics entity_specifics;
1953   {
1954     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1955     Cryptographer* cryptographer = trans.GetCryptographer();
1956     sync_pb::PasswordSpecificsData data;
1957     data.set_password_value("secret");
1958     cryptographer->Encrypt(
1959         data,
1960         entity_specifics.mutable_password()->
1961             mutable_encrypted());
1962   }
1963   MakeServerNode(sync_manager_.GetUserShare(), PASSWORDS, client_tag,
1964                  syncable::GenerateSyncableHash(PASSWORDS,
1965                                                 client_tag),
1966                  entity_specifics);
1967   // New node shouldn't start off unsynced.
1968   EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));
1969
1970   // Manually change to the same data via SetPasswordSpecifics. Should not set
1971   // is_unsynced.
1972   {
1973     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1974     WriteNode node(&trans);
1975     EXPECT_EQ(BaseNode::INIT_OK,
1976               node.InitByClientTagLookup(PASSWORDS, client_tag));
1977     node.SetPasswordSpecifics(node.GetPasswordSpecifics());
1978   }
1979   EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));
1980
1981   // Manually change to different data. Should set is_unsynced.
1982   {
1983     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
1984     WriteNode node(&trans);
1985     EXPECT_EQ(BaseNode::INIT_OK,
1986               node.InitByClientTagLookup(PASSWORDS, client_tag));
1987     Cryptographer* cryptographer = trans.GetCryptographer();
1988     sync_pb::PasswordSpecificsData data;
1989     data.set_password_value("secret2");
1990     cryptographer->Encrypt(
1991         data,
1992         entity_specifics.mutable_password()->mutable_encrypted());
1993     node.SetPasswordSpecifics(data);
1994     const syncable::Entry* node_entry = node.GetEntry();
1995     EXPECT_TRUE(node_entry->GetIsUnsynced());
1996   }
1997 }
1998
1999 // Passwords have their own handling for encryption. Verify setting a new
2000 // passphrase updates the data.
2001 TEST_F(SyncManagerTest, UpdatePasswordNewPassphrase) {
2002   std::string client_tag = "title";
2003   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
2004   sync_pb::EntitySpecifics entity_specifics;
2005   {
2006     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2007     Cryptographer* cryptographer = trans.GetCryptographer();
2008     sync_pb::PasswordSpecificsData data;
2009     data.set_password_value("secret");
2010     cryptographer->Encrypt(
2011         data,
2012         entity_specifics.mutable_password()->mutable_encrypted());
2013   }
2014   MakeServerNode(sync_manager_.GetUserShare(), PASSWORDS, client_tag,
2015                  syncable::GenerateSyncableHash(PASSWORDS,
2016                                                 client_tag),
2017                  entity_specifics);
2018   // New node shouldn't start off unsynced.
2019   EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));
2020
2021   // Set a new passphrase. Should set is_unsynced.
2022   testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
2023   EXPECT_CALL(encryption_observer_,
2024               OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
2025   EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
2026   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
2027   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
2028   EXPECT_CALL(encryption_observer_,
2029       OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
2030   sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
2031       "new_passphrase",
2032       true);
2033   EXPECT_EQ(CUSTOM_PASSPHRASE,
2034             sync_manager_.GetEncryptionHandler()->GetPassphraseType());
2035   EXPECT_TRUE(ResetUnsyncedEntry(PASSWORDS, client_tag));
2036 }
2037
2038 // Passwords have their own handling for encryption. Verify it does not result
2039 // in unnecessary writes via ReencryptEverything.
2040 TEST_F(SyncManagerTest, UpdatePasswordReencryptEverything) {
2041   std::string client_tag = "title";
2042   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
2043   sync_pb::EntitySpecifics entity_specifics;
2044   {
2045     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2046     Cryptographer* cryptographer = trans.GetCryptographer();
2047     sync_pb::PasswordSpecificsData data;
2048     data.set_password_value("secret");
2049     cryptographer->Encrypt(
2050         data,
2051         entity_specifics.mutable_password()->mutable_encrypted());
2052   }
2053   MakeServerNode(sync_manager_.GetUserShare(), PASSWORDS, client_tag,
2054                  syncable::GenerateSyncableHash(PASSWORDS,
2055                                                 client_tag),
2056                  entity_specifics);
2057   // New node shouldn't start off unsynced.
2058   EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));
2059
2060   // Force a re-encrypt everything. Should not set is_unsynced.
2061   testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
2062   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
2063   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
2064   EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));
2065   sync_manager_.GetEncryptionHandler()->Init();
2066   PumpLoop();
2067   EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));
2068 }
2069
2070 // Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for bookmarks
2071 // when we write the same data, but does set it when we write new data.
2072 TEST_F(SyncManagerTest, SetBookmarkTitle) {
2073   std::string client_tag = "title";
2074   sync_pb::EntitySpecifics entity_specifics;
2075   entity_specifics.mutable_bookmark()->set_url("url");
2076   entity_specifics.mutable_bookmark()->set_title("title");
2077   MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
2078                  syncable::GenerateSyncableHash(BOOKMARKS,
2079                                                 client_tag),
2080                  entity_specifics);
2081   // New node shouldn't start off unsynced.
2082   EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
2083
2084   // Manually change to the same title. Should not set is_unsynced.
2085   {
2086     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2087     WriteNode node(&trans);
2088     EXPECT_EQ(BaseNode::INIT_OK,
2089               node.InitByClientTagLookup(BOOKMARKS, client_tag));
2090     node.SetTitle(client_tag);
2091   }
2092   EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
2093
2094   // Manually change to new title. Should set is_unsynced.
2095   {
2096     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2097     WriteNode node(&trans);
2098     EXPECT_EQ(BaseNode::INIT_OK,
2099               node.InitByClientTagLookup(BOOKMARKS, client_tag));
2100     node.SetTitle("title2");
2101   }
2102   EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
2103 }
2104
2105 // Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for encrypted
2106 // bookmarks when we write the same data, but does set it when we write new
2107 // data.
2108 TEST_F(SyncManagerTest, SetBookmarkTitleWithEncryption) {
2109   std::string client_tag = "title";
2110   sync_pb::EntitySpecifics entity_specifics;
2111   entity_specifics.mutable_bookmark()->set_url("url");
2112   entity_specifics.mutable_bookmark()->set_title("title");
2113   MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
2114                  syncable::GenerateSyncableHash(BOOKMARKS,
2115                                                 client_tag),
2116                  entity_specifics);
2117   // New node shouldn't start off unsynced.
2118   EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
2119
2120   // Encrypt the datatatype, should set is_unsynced.
2121   EXPECT_CALL(encryption_observer_,
2122               OnEncryptedTypesChanged(
2123                   HasModelTypes(EncryptableUserTypes()), true));
2124   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
2125   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION));
2126   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
2127   EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, true));
2128   sync_manager_.GetEncryptionHandler()->Init();
2129   PumpLoop();
2130   EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
2131
2132   // Manually change to the same title. Should not set is_unsynced.
2133   // NON_UNIQUE_NAME should be kEncryptedString.
2134   {
2135     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2136     WriteNode node(&trans);
2137     EXPECT_EQ(BaseNode::INIT_OK,
2138               node.InitByClientTagLookup(BOOKMARKS, client_tag));
2139     node.SetTitle(client_tag);
2140     const syncable::Entry* node_entry = node.GetEntry();
2141     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
2142     EXPECT_TRUE(specifics.has_encrypted());
2143     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
2144   }
2145   EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
2146
2147   // Manually change to new title. Should set is_unsynced. NON_UNIQUE_NAME
2148   // should still be kEncryptedString.
2149   {
2150     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2151     WriteNode node(&trans);
2152     EXPECT_EQ(BaseNode::INIT_OK,
2153               node.InitByClientTagLookup(BOOKMARKS, client_tag));
2154     node.SetTitle("title2");
2155     const syncable::Entry* node_entry = node.GetEntry();
2156     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
2157     EXPECT_TRUE(specifics.has_encrypted());
2158     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
2159   }
2160   EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
2161 }
2162
2163 // Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for non-bookmarks
2164 // when we write the same data, but does set it when we write new data.
2165 TEST_F(SyncManagerTest, SetNonBookmarkTitle) {
2166   std::string client_tag = "title";
2167   sync_pb::EntitySpecifics entity_specifics;
2168   entity_specifics.mutable_preference()->set_name("name");
2169   entity_specifics.mutable_preference()->set_value("value");
2170   MakeServerNode(sync_manager_.GetUserShare(),
2171                  PREFERENCES,
2172                  client_tag,
2173                  syncable::GenerateSyncableHash(PREFERENCES,
2174                                                 client_tag),
2175                  entity_specifics);
2176   // New node shouldn't start off unsynced.
2177   EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, client_tag));
2178
2179   // Manually change to the same title. Should not set is_unsynced.
2180   {
2181     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2182     WriteNode node(&trans);
2183     EXPECT_EQ(BaseNode::INIT_OK,
2184               node.InitByClientTagLookup(PREFERENCES, client_tag));
2185     node.SetTitle(client_tag);
2186   }
2187   EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, client_tag));
2188
2189   // Manually change to new title. Should set is_unsynced.
2190   {
2191     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2192     WriteNode node(&trans);
2193     EXPECT_EQ(BaseNode::INIT_OK,
2194               node.InitByClientTagLookup(PREFERENCES, client_tag));
2195     node.SetTitle("title2");
2196   }
2197   EXPECT_TRUE(ResetUnsyncedEntry(PREFERENCES, client_tag));
2198 }
2199
2200 // Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for encrypted
2201 // non-bookmarks when we write the same data or when we write new data
2202 // data (should remained kEncryptedString).
2203 TEST_F(SyncManagerTest, SetNonBookmarkTitleWithEncryption) {
2204   std::string client_tag = "title";
2205   sync_pb::EntitySpecifics entity_specifics;
2206   entity_specifics.mutable_preference()->set_name("name");
2207   entity_specifics.mutable_preference()->set_value("value");
2208   MakeServerNode(sync_manager_.GetUserShare(),
2209                  PREFERENCES,
2210                  client_tag,
2211                  syncable::GenerateSyncableHash(PREFERENCES,
2212                                                 client_tag),
2213                  entity_specifics);
2214   // New node shouldn't start off unsynced.
2215   EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, client_tag));
2216
2217   // Encrypt the datatatype, should set is_unsynced.
2218   EXPECT_CALL(encryption_observer_,
2219               OnEncryptedTypesChanged(
2220                   HasModelTypes(EncryptableUserTypes()), true));
2221   EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
2222   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION));
2223   EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
2224   EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, true));
2225   sync_manager_.GetEncryptionHandler()->Init();
2226   PumpLoop();
2227   EXPECT_TRUE(ResetUnsyncedEntry(PREFERENCES, client_tag));
2228
2229   // Manually change to the same title. Should not set is_unsynced.
2230   // NON_UNIQUE_NAME should be kEncryptedString.
2231   {
2232     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2233     WriteNode node(&trans);
2234     EXPECT_EQ(BaseNode::INIT_OK,
2235               node.InitByClientTagLookup(PREFERENCES, client_tag));
2236     node.SetTitle(client_tag);
2237     const syncable::Entry* node_entry = node.GetEntry();
2238     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
2239     EXPECT_TRUE(specifics.has_encrypted());
2240     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
2241   }
2242   EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, client_tag));
2243
2244   // Manually change to new title. Should not set is_unsynced because the
2245   // NON_UNIQUE_NAME should still be kEncryptedString.
2246   {
2247     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2248     WriteNode node(&trans);
2249     EXPECT_EQ(BaseNode::INIT_OK,
2250               node.InitByClientTagLookup(PREFERENCES, client_tag));
2251     node.SetTitle("title2");
2252     const syncable::Entry* node_entry = node.GetEntry();
2253     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
2254     EXPECT_TRUE(specifics.has_encrypted());
2255     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
2256     EXPECT_FALSE(node_entry->GetIsUnsynced());
2257   }
2258 }
2259
2260 // Ensure that titles are truncated to 255 bytes, and attempting to reset
2261 // them to their longer version does not set IS_UNSYNCED.
2262 TEST_F(SyncManagerTest, SetLongTitle) {
2263   const int kNumChars = 512;
2264   const std::string kClientTag = "tag";
2265   std::string title(kNumChars, '0');
2266   sync_pb::EntitySpecifics entity_specifics;
2267   entity_specifics.mutable_preference()->set_name("name");
2268   entity_specifics.mutable_preference()->set_value("value");
2269   MakeServerNode(sync_manager_.GetUserShare(),
2270                  PREFERENCES,
2271                  "short_title",
2272                  syncable::GenerateSyncableHash(PREFERENCES,
2273                                                 kClientTag),
2274                  entity_specifics);
2275   // New node shouldn't start off unsynced.
2276   EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, kClientTag));
2277
2278   // Manually change to the long title. Should set is_unsynced.
2279   {
2280     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2281     WriteNode node(&trans);
2282     EXPECT_EQ(BaseNode::INIT_OK,
2283               node.InitByClientTagLookup(PREFERENCES, kClientTag));
2284     node.SetTitle(title);
2285     EXPECT_EQ(node.GetTitle(), title.substr(0, 255));
2286   }
2287   EXPECT_TRUE(ResetUnsyncedEntry(PREFERENCES, kClientTag));
2288
2289   // Manually change to the same title. Should not set is_unsynced.
2290   {
2291     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2292     WriteNode node(&trans);
2293     EXPECT_EQ(BaseNode::INIT_OK,
2294               node.InitByClientTagLookup(PREFERENCES, kClientTag));
2295     node.SetTitle(title);
2296     EXPECT_EQ(node.GetTitle(), title.substr(0, 255));
2297   }
2298   EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, kClientTag));
2299
2300   // Manually change to new title. Should set is_unsynced.
2301   {
2302     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2303     WriteNode node(&trans);
2304     EXPECT_EQ(BaseNode::INIT_OK,
2305               node.InitByClientTagLookup(PREFERENCES, kClientTag));
2306     node.SetTitle("title2");
2307   }
2308   EXPECT_TRUE(ResetUnsyncedEntry(PREFERENCES, kClientTag));
2309 }
2310
2311 // Create an encrypted entry when the cryptographer doesn't think the type is
2312 // marked for encryption. Ensure reads/writes don't break and don't unencrypt
2313 // the data.
2314 TEST_F(SyncManagerTest, SetPreviouslyEncryptedSpecifics) {
2315   std::string client_tag = "tag";
2316   std::string url = "url";
2317   std::string url2 = "new_url";
2318   std::string title = "title";
2319   sync_pb::EntitySpecifics entity_specifics;
2320   EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
2321   {
2322     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2323     Cryptographer* crypto = trans.GetCryptographer();
2324     sync_pb::EntitySpecifics bm_specifics;
2325     bm_specifics.mutable_bookmark()->set_title("title");
2326     bm_specifics.mutable_bookmark()->set_url("url");
2327     sync_pb::EncryptedData encrypted;
2328     crypto->Encrypt(bm_specifics, &encrypted);
2329     entity_specifics.mutable_encrypted()->CopyFrom(encrypted);
2330     AddDefaultFieldValue(BOOKMARKS, &entity_specifics);
2331   }
2332   MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
2333                  syncable::GenerateSyncableHash(BOOKMARKS,
2334                                                 client_tag),
2335                  entity_specifics);
2336
2337   {
2338     // Verify the data.
2339     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2340     ReadNode node(&trans);
2341     EXPECT_EQ(BaseNode::INIT_OK,
2342               node.InitByClientTagLookup(BOOKMARKS, client_tag));
2343     EXPECT_EQ(title, node.GetTitle());
2344     EXPECT_EQ(url, node.GetBookmarkSpecifics().url());
2345   }
2346
2347   {
2348     // Overwrite the url (which overwrites the specifics).
2349     WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2350     WriteNode node(&trans);
2351     EXPECT_EQ(BaseNode::INIT_OK,
2352               node.InitByClientTagLookup(BOOKMARKS, client_tag));
2353
2354     sync_pb::BookmarkSpecifics bookmark_specifics(node.GetBookmarkSpecifics());
2355     bookmark_specifics.set_url(url2);
2356     node.SetBookmarkSpecifics(bookmark_specifics);
2357   }
2358
2359   {
2360     // Verify it's still encrypted and it has the most recent url.
2361     ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
2362     ReadNode node(&trans);
2363     EXPECT_EQ(BaseNode::INIT_OK,
2364               node.InitByClientTagLookup(BOOKMARKS, client_tag));
2365     EXPECT_EQ(title, node.GetTitle());
2366     EXPECT_EQ(url2, node.GetBookmarkSpecifics().url());
2367     const syncable::Entry* node_entry = node.GetEntry();
2368     EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
2369     const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
2370     EXPECT_TRUE(specifics.has_encrypted());
2371   }
2372 }
2373
2374 // Verify transaction version of a model type is incremented when node of
2375 // that type is updated.
2376 TEST_F(SyncManagerTest, IncrementTransactionVersion) {
2377   ModelSafeRoutingInfo routing_info;
2378   GetModelSafeRoutingInfo(&routing_info);
2379
2380   {
2381     ReadTransaction read_trans(FROM_HERE, sync_manager_.GetUserShare());
2382     for (ModelSafeRoutingInfo::iterator i = routing_info.begin();
2383          i != routing_info.end(); ++i) {
2384       // Transaction version is incremented when SyncManagerTest::SetUp()
2385       // creates a node of each type.
2386       EXPECT_EQ(1,
2387                 sync_manager_.GetUserShare()->directory->
2388                     GetTransactionVersion(i->first));
2389     }
2390   }
2391
2392   // Create bookmark node to increment transaction version of bookmark model.
2393   std::string client_tag = "title";
2394   sync_pb::EntitySpecifics entity_specifics;
2395   entity_specifics.mutable_bookmark()->set_url("url");
2396   entity_specifics.mutable_bookmark()->set_title("title");
2397   MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
2398                  syncable::GenerateSyncableHash(BOOKMARKS,
2399                                                 client_tag),
2400                  entity_specifics);
2401
2402   {
2403     ReadTransaction read_trans(FROM_HERE, sync_manager_.GetUserShare());
2404     for (ModelSafeRoutingInfo::iterator i = routing_info.begin();
2405          i != routing_info.end(); ++i) {
2406       EXPECT_EQ(i->first == BOOKMARKS ? 2 : 1,
2407                 sync_manager_.GetUserShare()->directory->
2408                     GetTransactionVersion(i->first));
2409     }
2410   }
2411 }
2412
2413 class MockSyncScheduler : public FakeSyncScheduler {
2414  public:
2415   MockSyncScheduler() : FakeSyncScheduler() {}
2416   virtual ~MockSyncScheduler() {}
2417
2418   MOCK_METHOD1(Start, void(SyncScheduler::Mode));
2419   MOCK_METHOD1(ScheduleConfiguration, void(const ConfigurationParams&));
2420 };
2421
2422 class ComponentsFactory : public TestInternalComponentsFactory {
2423  public:
2424   ComponentsFactory(const Switches& switches,
2425                     SyncScheduler* scheduler_to_use,
2426                     sessions::SyncSessionContext** session_context)
2427       : TestInternalComponentsFactory(switches, syncer::STORAGE_IN_MEMORY),
2428         scheduler_to_use_(scheduler_to_use),
2429         session_context_(session_context) {}
2430   virtual ~ComponentsFactory() {}
2431
2432   virtual scoped_ptr<SyncScheduler> BuildScheduler(
2433       const std::string& name,
2434       sessions::SyncSessionContext* context,
2435       CancelationSignal* stop_handle) OVERRIDE {
2436     *session_context_ = context;
2437     return scheduler_to_use_.Pass();
2438   }
2439
2440  private:
2441   scoped_ptr<SyncScheduler> scheduler_to_use_;
2442   sessions::SyncSessionContext** session_context_;
2443 };
2444
2445 class SyncManagerTestWithMockScheduler : public SyncManagerTest {
2446  public:
2447   SyncManagerTestWithMockScheduler() : scheduler_(NULL) {}
2448   virtual InternalComponentsFactory* GetFactory() OVERRIDE {
2449     scheduler_ = new MockSyncScheduler();
2450     return new ComponentsFactory(GetSwitches(), scheduler_, &session_context_);
2451   }
2452
2453   MockSyncScheduler* scheduler() { return scheduler_; }
2454   sessions::SyncSessionContext* session_context() {
2455       return session_context_;
2456   }
2457
2458  private:
2459   MockSyncScheduler* scheduler_;
2460   sessions::SyncSessionContext* session_context_;
2461 };
2462
2463 // Test that the configuration params are properly created and sent to
2464 // ScheduleConfigure. No callback should be invoked. Any disabled datatypes
2465 // should be purged.
2466 TEST_F(SyncManagerTestWithMockScheduler, BasicConfiguration) {
2467   ConfigureReason reason = CONFIGURE_REASON_RECONFIGURATION;
2468   ModelTypeSet types_to_download(BOOKMARKS, PREFERENCES);
2469   ModelSafeRoutingInfo new_routing_info;
2470   GetModelSafeRoutingInfo(&new_routing_info);
2471   ModelTypeSet enabled_types = GetRoutingInfoTypes(new_routing_info);
2472   ModelTypeSet disabled_types = Difference(ModelTypeSet::All(), enabled_types);
2473
2474   ConfigurationParams params;
2475   EXPECT_CALL(*scheduler(), Start(SyncScheduler::CONFIGURATION_MODE));
2476   EXPECT_CALL(*scheduler(), ScheduleConfiguration(_)).
2477       WillOnce(SaveArg<0>(&params));
2478
2479   // Set data for all types.
2480   ModelTypeSet protocol_types = ProtocolTypes();
2481   for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
2482        iter.Inc()) {
2483     SetProgressMarkerForType(iter.Get(), true);
2484   }
2485
2486   CallbackCounter ready_task_counter, retry_task_counter;
2487   sync_manager_.ConfigureSyncer(
2488       reason,
2489       types_to_download,
2490       disabled_types,
2491       ModelTypeSet(),
2492       ModelTypeSet(),
2493       new_routing_info,
2494       base::Bind(&CallbackCounter::Callback,
2495                  base::Unretained(&ready_task_counter)),
2496       base::Bind(&CallbackCounter::Callback,
2497                  base::Unretained(&retry_task_counter)));
2498   EXPECT_EQ(0, ready_task_counter.times_called());
2499   EXPECT_EQ(0, retry_task_counter.times_called());
2500   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION,
2501             params.source);
2502   EXPECT_TRUE(types_to_download.Equals(params.types_to_download));
2503   EXPECT_EQ(new_routing_info, params.routing_info);
2504
2505   // Verify all the disabled types were purged.
2506   EXPECT_TRUE(sync_manager_.InitialSyncEndedTypes().Equals(
2507       enabled_types));
2508   EXPECT_TRUE(sync_manager_.GetTypesWithEmptyProgressMarkerToken(
2509       ModelTypeSet::All()).Equals(disabled_types));
2510 }
2511
2512 // Test that on a reconfiguration (configuration where the session context
2513 // already has routing info), only those recently disabled types are purged.
2514 TEST_F(SyncManagerTestWithMockScheduler, ReConfiguration) {
2515   ConfigureReason reason = CONFIGURE_REASON_RECONFIGURATION;
2516   ModelTypeSet types_to_download(BOOKMARKS, PREFERENCES);
2517   ModelTypeSet disabled_types = ModelTypeSet(THEMES, SESSIONS);
2518   ModelSafeRoutingInfo old_routing_info;
2519   ModelSafeRoutingInfo new_routing_info;
2520   GetModelSafeRoutingInfo(&old_routing_info);
2521   new_routing_info = old_routing_info;
2522   new_routing_info.erase(THEMES);
2523   new_routing_info.erase(SESSIONS);
2524   ModelTypeSet enabled_types = GetRoutingInfoTypes(new_routing_info);
2525
2526   ConfigurationParams params;
2527   EXPECT_CALL(*scheduler(), Start(SyncScheduler::CONFIGURATION_MODE));
2528   EXPECT_CALL(*scheduler(), ScheduleConfiguration(_)).
2529       WillOnce(SaveArg<0>(&params));
2530
2531   // Set data for all types except those recently disabled (so we can verify
2532   // only those recently disabled are purged) .
2533   ModelTypeSet protocol_types = ProtocolTypes();
2534   for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
2535        iter.Inc()) {
2536     if (!disabled_types.Has(iter.Get())) {
2537       SetProgressMarkerForType(iter.Get(), true);
2538     } else {
2539       SetProgressMarkerForType(iter.Get(), false);
2540     }
2541   }
2542
2543   // Set the context to have the old routing info.
2544   session_context()->SetRoutingInfo(old_routing_info);
2545
2546   CallbackCounter ready_task_counter, retry_task_counter;
2547   sync_manager_.ConfigureSyncer(
2548       reason,
2549       types_to_download,
2550       ModelTypeSet(),
2551       ModelTypeSet(),
2552       ModelTypeSet(),
2553       new_routing_info,
2554       base::Bind(&CallbackCounter::Callback,
2555                  base::Unretained(&ready_task_counter)),
2556       base::Bind(&CallbackCounter::Callback,
2557                  base::Unretained(&retry_task_counter)));
2558   EXPECT_EQ(0, ready_task_counter.times_called());
2559   EXPECT_EQ(0, retry_task_counter.times_called());
2560   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION,
2561             params.source);
2562   EXPECT_TRUE(types_to_download.Equals(params.types_to_download));
2563   EXPECT_EQ(new_routing_info, params.routing_info);
2564
2565   // Verify only the recently disabled types were purged.
2566   EXPECT_TRUE(sync_manager_.GetTypesWithEmptyProgressMarkerToken(
2567       ProtocolTypes()).Equals(disabled_types));
2568 }
2569
2570 // Test that PurgePartiallySyncedTypes purges only those types that have not
2571 // fully completed their initial download and apply.
2572 TEST_F(SyncManagerTest, PurgePartiallySyncedTypes) {
2573   ModelSafeRoutingInfo routing_info;
2574   GetModelSafeRoutingInfo(&routing_info);
2575   ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
2576
2577   UserShare* share = sync_manager_.GetUserShare();
2578
2579   // The test harness automatically initializes all types in the routing info.
2580   // Check that autofill is not among them.
2581   ASSERT_FALSE(enabled_types.Has(AUTOFILL));
2582
2583   // Further ensure that the test harness did not create its root node.
2584   {
2585     syncable::ReadTransaction trans(FROM_HERE, share->directory.get());
2586     syncable::Entry autofill_root_node(&trans, syncable::GET_BY_SERVER_TAG,
2587                                        ModelTypeToRootTag(AUTOFILL));
2588     ASSERT_FALSE(autofill_root_node.good());
2589   }
2590
2591   // One more redundant check.
2592   ASSERT_FALSE(sync_manager_.InitialSyncEndedTypes().Has(AUTOFILL));
2593
2594   // Give autofill a progress marker.
2595   sync_pb::DataTypeProgressMarker autofill_marker;
2596   autofill_marker.set_data_type_id(
2597       GetSpecificsFieldNumberFromModelType(AUTOFILL));
2598   autofill_marker.set_token("token");
2599   share->directory->SetDownloadProgress(AUTOFILL, autofill_marker);
2600
2601   // Also add a pending autofill root node update from the server.
2602   TestEntryFactory factory_(share->directory.get());
2603   int autofill_meta = factory_.CreateUnappliedRootNode(AUTOFILL);
2604
2605   // Preferences is an enabled type.  Check that the harness initialized it.
2606   ASSERT_TRUE(enabled_types.Has(PREFERENCES));
2607   ASSERT_TRUE(sync_manager_.InitialSyncEndedTypes().Has(PREFERENCES));
2608
2609   // Give preferencse a progress marker.
2610   sync_pb::DataTypeProgressMarker prefs_marker;
2611   prefs_marker.set_data_type_id(
2612       GetSpecificsFieldNumberFromModelType(PREFERENCES));
2613   prefs_marker.set_token("token");
2614   share->directory->SetDownloadProgress(PREFERENCES, prefs_marker);
2615
2616   // Add a fully synced preferences node under the root.
2617   std::string pref_client_tag = "prefABC";
2618   std::string pref_hashed_tag = "hashXYZ";
2619   sync_pb::EntitySpecifics pref_specifics;
2620   AddDefaultFieldValue(PREFERENCES, &pref_specifics);
2621   int pref_meta = MakeServerNode(
2622       share, PREFERENCES, pref_client_tag, pref_hashed_tag, pref_specifics);
2623
2624   // And now, the purge.
2625   EXPECT_TRUE(sync_manager_.PurgePartiallySyncedTypes());
2626
2627   // Ensure that autofill lost its progress marker, but preferences did not.
2628   ModelTypeSet empty_tokens =
2629       sync_manager_.GetTypesWithEmptyProgressMarkerToken(ModelTypeSet::All());
2630   EXPECT_TRUE(empty_tokens.Has(AUTOFILL));
2631   EXPECT_FALSE(empty_tokens.Has(PREFERENCES));
2632
2633   // Ensure that autofill lots its node, but preferences did not.
2634   {
2635     syncable::ReadTransaction trans(FROM_HERE, share->directory.get());
2636     syncable::Entry autofill_node(&trans, GET_BY_HANDLE, autofill_meta);
2637     syncable::Entry pref_node(&trans, GET_BY_HANDLE, pref_meta);
2638     EXPECT_FALSE(autofill_node.good());
2639     EXPECT_TRUE(pref_node.good());
2640   }
2641 }
2642
2643 // Test CleanupDisabledTypes properly purges all disabled types as specified
2644 // by the previous and current enabled params.
2645 TEST_F(SyncManagerTest, PurgeDisabledTypes) {
2646   ModelSafeRoutingInfo routing_info;
2647   GetModelSafeRoutingInfo(&routing_info);
2648   ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
2649   ModelTypeSet disabled_types = Difference(ModelTypeSet::All(), enabled_types);
2650
2651   // The harness should have initialized the enabled_types for us.
2652   EXPECT_TRUE(enabled_types.Equals(sync_manager_.InitialSyncEndedTypes()));
2653
2654   // Set progress markers for all types.
2655   ModelTypeSet protocol_types = ProtocolTypes();
2656   for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
2657        iter.Inc()) {
2658     SetProgressMarkerForType(iter.Get(), true);
2659   }
2660
2661   // Verify all the enabled types remain after cleanup, and all the disabled
2662   // types were purged.
2663   sync_manager_.PurgeDisabledTypes(disabled_types,
2664                                    ModelTypeSet(),
2665                                    ModelTypeSet());
2666   EXPECT_TRUE(enabled_types.Equals(sync_manager_.InitialSyncEndedTypes()));
2667   EXPECT_TRUE(disabled_types.Equals(
2668       sync_manager_.GetTypesWithEmptyProgressMarkerToken(ModelTypeSet::All())));
2669
2670   // Disable some more types.
2671   disabled_types.Put(BOOKMARKS);
2672   disabled_types.Put(PREFERENCES);
2673   ModelTypeSet new_enabled_types =
2674       Difference(ModelTypeSet::All(), disabled_types);
2675
2676   // Verify only the non-disabled types remain after cleanup.
2677   sync_manager_.PurgeDisabledTypes(disabled_types,
2678                                    ModelTypeSet(),
2679                                    ModelTypeSet());
2680   EXPECT_TRUE(new_enabled_types.Equals(sync_manager_.InitialSyncEndedTypes()));
2681   EXPECT_TRUE(disabled_types.Equals(
2682       sync_manager_.GetTypesWithEmptyProgressMarkerToken(ModelTypeSet::All())));
2683 }
2684
2685 // Test PurgeDisabledTypes properly unapplies types by deleting their local data
2686 // and preserving their server data and progress marker.
2687 TEST_F(SyncManagerTest, PurgeUnappliedTypes) {
2688   ModelSafeRoutingInfo routing_info;
2689   GetModelSafeRoutingInfo(&routing_info);
2690   ModelTypeSet unapplied_types = ModelTypeSet(BOOKMARKS, PREFERENCES);
2691   ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
2692   ModelTypeSet disabled_types = Difference(ModelTypeSet::All(), enabled_types);
2693
2694   // The harness should have initialized the enabled_types for us.
2695   EXPECT_TRUE(enabled_types.Equals(sync_manager_.InitialSyncEndedTypes()));
2696
2697   // Set progress markers for all types.
2698   ModelTypeSet protocol_types = ProtocolTypes();
2699   for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
2700        iter.Inc()) {
2701     SetProgressMarkerForType(iter.Get(), true);
2702   }
2703
2704   // Add the following kinds of items:
2705   // 1. Fully synced preference.
2706   // 2. Locally created preference, server unknown, unsynced
2707   // 3. Locally deleted preference, server known, unsynced
2708   // 4. Server deleted preference, locally known.
2709   // 5. Server created preference, locally unknown, unapplied.
2710   // 6. A fully synced bookmark (no unique_client_tag).
2711   UserShare* share = sync_manager_.GetUserShare();
2712   sync_pb::EntitySpecifics pref_specifics;
2713   AddDefaultFieldValue(PREFERENCES, &pref_specifics);
2714   sync_pb::EntitySpecifics bm_specifics;
2715   AddDefaultFieldValue(BOOKMARKS, &bm_specifics);
2716   int pref1_meta = MakeServerNode(
2717       share, PREFERENCES, "pref1", "hash1", pref_specifics);
2718   int64 pref2_meta = MakeNode(share, PREFERENCES, "pref2");
2719   int pref3_meta = MakeServerNode(
2720       share, PREFERENCES, "pref3", "hash3", pref_specifics);
2721   int pref4_meta = MakeServerNode(
2722       share, PREFERENCES, "pref4", "hash4", pref_specifics);
2723   int pref5_meta = MakeServerNode(
2724       share, PREFERENCES, "pref5", "hash5", pref_specifics);
2725   int bookmark_meta = MakeServerNode(
2726       share, BOOKMARKS, "bookmark", "", bm_specifics);
2727
2728   {
2729     syncable::WriteTransaction trans(FROM_HERE,
2730                                      syncable::SYNCER,
2731                                      share->directory.get());
2732     // Pref's 1 and 2 are already set up properly.
2733     // Locally delete pref 3.
2734     syncable::MutableEntry pref3(&trans, GET_BY_HANDLE, pref3_meta);
2735     pref3.PutIsDel(true);
2736     pref3.PutIsUnsynced(true);
2737     // Delete pref 4 at the server.
2738     syncable::MutableEntry pref4(&trans, GET_BY_HANDLE, pref4_meta);
2739     pref4.PutServerIsDel(true);
2740     pref4.PutIsUnappliedUpdate(true);
2741     pref4.PutServerVersion(2);
2742     // Pref 5 is an new unapplied update.
2743     syncable::MutableEntry pref5(&trans, GET_BY_HANDLE, pref5_meta);
2744     pref5.PutIsUnappliedUpdate(true);
2745     pref5.PutIsDel(true);
2746     pref5.PutBaseVersion(-1);
2747     // Bookmark is already set up properly
2748   }
2749
2750   // Take a snapshot to clear all the dirty bits.
2751   share->directory.get()->SaveChanges();
2752
2753   // Now request a purge for the unapplied types.
2754   disabled_types.PutAll(unapplied_types);
2755   sync_manager_.PurgeDisabledTypes(disabled_types,
2756                                    ModelTypeSet(),
2757                                    unapplied_types);
2758
2759   // Verify the unapplied types still have progress markers and initial sync
2760   // ended after cleanup.
2761   EXPECT_TRUE(sync_manager_.InitialSyncEndedTypes().HasAll(unapplied_types));
2762   EXPECT_TRUE(
2763       sync_manager_.GetTypesWithEmptyProgressMarkerToken(unapplied_types).
2764           Empty());
2765
2766   // Ensure the items were unapplied as necessary.
2767   {
2768     syncable::ReadTransaction trans(FROM_HERE, share->directory.get());
2769     syncable::Entry pref_node(&trans, GET_BY_HANDLE, pref1_meta);
2770     ASSERT_TRUE(pref_node.good());
2771     EXPECT_TRUE(pref_node.GetKernelCopy().is_dirty());
2772     EXPECT_FALSE(pref_node.GetIsUnsynced());
2773     EXPECT_TRUE(pref_node.GetIsUnappliedUpdate());
2774     EXPECT_TRUE(pref_node.GetIsDel());
2775     EXPECT_GT(pref_node.GetServerVersion(), 0);
2776     EXPECT_EQ(pref_node.GetBaseVersion(), -1);
2777
2778     // Pref 2 should just be locally deleted.
2779     syncable::Entry pref2_node(&trans, GET_BY_HANDLE, pref2_meta);
2780     ASSERT_TRUE(pref2_node.good());
2781     EXPECT_TRUE(pref2_node.GetKernelCopy().is_dirty());
2782     EXPECT_FALSE(pref2_node.GetIsUnsynced());
2783     EXPECT_TRUE(pref2_node.GetIsDel());
2784     EXPECT_FALSE(pref2_node.GetIsUnappliedUpdate());
2785     EXPECT_TRUE(pref2_node.GetIsDel());
2786     EXPECT_EQ(pref2_node.GetServerVersion(), 0);
2787     EXPECT_EQ(pref2_node.GetBaseVersion(), -1);
2788
2789     syncable::Entry pref3_node(&trans, GET_BY_HANDLE, pref3_meta);
2790     ASSERT_TRUE(pref3_node.good());
2791     EXPECT_TRUE(pref3_node.GetKernelCopy().is_dirty());
2792     EXPECT_FALSE(pref3_node.GetIsUnsynced());
2793     EXPECT_TRUE(pref3_node.GetIsUnappliedUpdate());
2794     EXPECT_TRUE(pref3_node.GetIsDel());
2795     EXPECT_GT(pref3_node.GetServerVersion(), 0);
2796     EXPECT_EQ(pref3_node.GetBaseVersion(), -1);
2797
2798     syncable::Entry pref4_node(&trans, GET_BY_HANDLE, pref4_meta);
2799     ASSERT_TRUE(pref4_node.good());
2800     EXPECT_TRUE(pref4_node.GetKernelCopy().is_dirty());
2801     EXPECT_FALSE(pref4_node.GetIsUnsynced());
2802     EXPECT_TRUE(pref4_node.GetIsUnappliedUpdate());
2803     EXPECT_TRUE(pref4_node.GetIsDel());
2804     EXPECT_GT(pref4_node.GetServerVersion(), 0);
2805     EXPECT_EQ(pref4_node.GetBaseVersion(), -1);
2806
2807     // Pref 5 should remain untouched.
2808     syncable::Entry pref5_node(&trans, GET_BY_HANDLE, pref5_meta);
2809     ASSERT_TRUE(pref5_node.good());
2810     EXPECT_FALSE(pref5_node.GetKernelCopy().is_dirty());
2811     EXPECT_FALSE(pref5_node.GetIsUnsynced());
2812     EXPECT_TRUE(pref5_node.GetIsUnappliedUpdate());
2813     EXPECT_TRUE(pref5_node.GetIsDel());
2814     EXPECT_GT(pref5_node.GetServerVersion(), 0);
2815     EXPECT_EQ(pref5_node.GetBaseVersion(), -1);
2816
2817     syncable::Entry bookmark_node(&trans, GET_BY_HANDLE, bookmark_meta);
2818     ASSERT_TRUE(bookmark_node.good());
2819     EXPECT_TRUE(bookmark_node.GetKernelCopy().is_dirty());
2820     EXPECT_FALSE(bookmark_node.GetIsUnsynced());
2821     EXPECT_TRUE(bookmark_node.GetIsUnappliedUpdate());
2822     EXPECT_TRUE(bookmark_node.GetIsDel());
2823     EXPECT_GT(bookmark_node.GetServerVersion(), 0);
2824     EXPECT_EQ(bookmark_node.GetBaseVersion(), -1);
2825   }
2826 }
2827
2828 // A test harness to exercise the code that processes and passes changes from
2829 // the "SYNCER"-WriteTransaction destructor, through the SyncManager, to the
2830 // ChangeProcessor.
2831 class SyncManagerChangeProcessingTest : public SyncManagerTest {
2832  public:
2833   virtual void OnChangesApplied(
2834       ModelType model_type,
2835       int64 model_version,
2836       const BaseTransaction* trans,
2837       const ImmutableChangeRecordList& changes) OVERRIDE {
2838     last_changes_ = changes;
2839   }
2840
2841   virtual void OnChangesComplete(ModelType model_type) OVERRIDE {}
2842
2843   const ImmutableChangeRecordList& GetRecentChangeList() {
2844     return last_changes_;
2845   }
2846
2847   UserShare* share() {
2848     return sync_manager_.GetUserShare();
2849   }
2850
2851   // Set some flags so our nodes reasonably approximate the real world scenario
2852   // and can get past CheckTreeInvariants.
2853   //
2854   // It's never going to be truly accurate, since we're squashing update
2855   // receipt, processing and application into a single transaction.
2856   void SetNodeProperties(syncable::MutableEntry *entry) {
2857     entry->PutId(id_factory_.NewServerId());
2858     entry->PutBaseVersion(10);
2859     entry->PutServerVersion(10);
2860   }
2861
2862   // Looks for the given change in the list.  Returns the index at which it was
2863   // found.  Returns -1 on lookup failure.
2864   size_t FindChangeInList(int64 id, ChangeRecord::Action action) {
2865     SCOPED_TRACE(id);
2866     for (size_t i = 0; i < last_changes_.Get().size(); ++i) {
2867       if (last_changes_.Get()[i].id == id
2868           && last_changes_.Get()[i].action == action) {
2869         return i;
2870       }
2871     }
2872     ADD_FAILURE() << "Failed to find specified change";
2873     return -1;
2874   }
2875
2876   // Returns the current size of the change list.
2877   //
2878   // Note that spurious changes do not necessarily indicate a problem.
2879   // Assertions on change list size can help detect problems, but it may be
2880   // necessary to reduce their strictness if the implementation changes.
2881   size_t GetChangeListSize() {
2882     return last_changes_.Get().size();
2883   }
2884
2885  protected:
2886   ImmutableChangeRecordList last_changes_;
2887   TestIdFactory id_factory_;
2888 };
2889
2890 // Test creation of a folder and a bookmark.
2891 TEST_F(SyncManagerChangeProcessingTest, AddBookmarks) {
2892   int64 type_root = GetIdForDataType(BOOKMARKS);
2893   int64 folder_id = kInvalidId;
2894   int64 child_id = kInvalidId;
2895
2896   // Create a folder and a bookmark under it.
2897   {
2898     syncable::WriteTransaction trans(
2899         FROM_HERE, syncable::SYNCER, share()->directory.get());
2900     syncable::Entry root(&trans, syncable::GET_BY_HANDLE, type_root);
2901     ASSERT_TRUE(root.good());
2902
2903     syncable::MutableEntry folder(&trans, syncable::CREATE,
2904                                   BOOKMARKS, root.GetId(), "folder");
2905     ASSERT_TRUE(folder.good());
2906     SetNodeProperties(&folder);
2907     folder.PutIsDir(true);
2908     folder_id = folder.GetMetahandle();
2909
2910     syncable::MutableEntry child(&trans, syncable::CREATE,
2911                                  BOOKMARKS, folder.GetId(), "child");
2912     ASSERT_TRUE(child.good());
2913     SetNodeProperties(&child);
2914     child_id = child.GetMetahandle();
2915   }
2916
2917   // The closing of the above scope will delete the transaction.  Its processed
2918   // changes should be waiting for us in a member of the test harness.
2919   EXPECT_EQ(2UL, GetChangeListSize());
2920
2921   // We don't need to check these return values here.  The function will add a
2922   // non-fatal failure if these changes are not found.
2923   size_t folder_change_pos =
2924       FindChangeInList(folder_id, ChangeRecord::ACTION_ADD);
2925   size_t child_change_pos =
2926       FindChangeInList(child_id, ChangeRecord::ACTION_ADD);
2927
2928   // Parents are delivered before children.
2929   EXPECT_LT(folder_change_pos, child_change_pos);
2930 }
2931
2932 // Test moving a bookmark into an empty folder.
2933 TEST_F(SyncManagerChangeProcessingTest, MoveBookmarkIntoEmptyFolder) {
2934   int64 type_root = GetIdForDataType(BOOKMARKS);
2935   int64 folder_b_id = kInvalidId;
2936   int64 child_id = kInvalidId;
2937
2938   // Create two folders.  Place a child under folder A.
2939   {
2940     syncable::WriteTransaction trans(
2941         FROM_HERE, syncable::SYNCER, share()->directory.get());
2942     syncable::Entry root(&trans, syncable::GET_BY_HANDLE, type_root);
2943     ASSERT_TRUE(root.good());
2944
2945     syncable::MutableEntry folder_a(&trans, syncable::CREATE,
2946                                     BOOKMARKS, root.GetId(), "folderA");
2947     ASSERT_TRUE(folder_a.good());
2948     SetNodeProperties(&folder_a);
2949     folder_a.PutIsDir(true);
2950
2951     syncable::MutableEntry folder_b(&trans, syncable::CREATE,
2952                                     BOOKMARKS, root.GetId(), "folderB");
2953     ASSERT_TRUE(folder_b.good());
2954     SetNodeProperties(&folder_b);
2955     folder_b.PutIsDir(true);
2956     folder_b_id = folder_b.GetMetahandle();
2957
2958     syncable::MutableEntry child(&trans, syncable::CREATE,
2959                                  BOOKMARKS, folder_a.GetId(),
2960                                  "child");
2961     ASSERT_TRUE(child.good());
2962     SetNodeProperties(&child);
2963     child_id = child.GetMetahandle();
2964   }
2965
2966   // Close that transaction.  The above was to setup the initial scenario.  The
2967   // real test starts now.
2968
2969   // Move the child from folder A to folder B.
2970   {
2971     syncable::WriteTransaction trans(
2972         FROM_HERE, syncable::SYNCER, share()->directory.get());
2973
2974     syncable::Entry folder_b(&trans, syncable::GET_BY_HANDLE, folder_b_id);
2975     syncable::MutableEntry child(&trans, syncable::GET_BY_HANDLE, child_id);
2976
2977     child.PutParentId(folder_b.GetId());
2978   }
2979
2980   EXPECT_EQ(1UL, GetChangeListSize());
2981
2982   // Verify that this was detected as a real change.  An early version of the
2983   // UniquePosition code had a bug where moves from one folder to another were
2984   // ignored unless the moved node's UniquePosition value was also changed in
2985   // some way.
2986   FindChangeInList(child_id, ChangeRecord::ACTION_UPDATE);
2987 }
2988
2989 // Test moving a bookmark into a non-empty folder.
2990 TEST_F(SyncManagerChangeProcessingTest, MoveIntoPopulatedFolder) {
2991   int64 type_root = GetIdForDataType(BOOKMARKS);
2992   int64 child_a_id = kInvalidId;
2993   int64 child_b_id = kInvalidId;
2994
2995   // Create two folders.  Place one child each under folder A and folder B.
2996   {
2997     syncable::WriteTransaction trans(
2998         FROM_HERE, syncable::SYNCER, share()->directory.get());
2999     syncable::Entry root(&trans, syncable::GET_BY_HANDLE, type_root);
3000     ASSERT_TRUE(root.good());
3001
3002     syncable::MutableEntry folder_a(&trans, syncable::CREATE,
3003                                     BOOKMARKS, root.GetId(), "folderA");
3004     ASSERT_TRUE(folder_a.good());
3005     SetNodeProperties(&folder_a);
3006     folder_a.PutIsDir(true);
3007
3008     syncable::MutableEntry folder_b(&trans, syncable::CREATE,
3009                                     BOOKMARKS, root.GetId(), "folderB");
3010     ASSERT_TRUE(folder_b.good());
3011     SetNodeProperties(&folder_b);
3012     folder_b.PutIsDir(true);
3013
3014     syncable::MutableEntry child_a(&trans, syncable::CREATE,
3015                                    BOOKMARKS, folder_a.GetId(),
3016                                    "childA");
3017     ASSERT_TRUE(child_a.good());
3018     SetNodeProperties(&child_a);
3019     child_a_id = child_a.GetMetahandle();
3020
3021     syncable::MutableEntry child_b(&trans, syncable::CREATE,
3022                                    BOOKMARKS, folder_b.GetId(),
3023                                    "childB");
3024     SetNodeProperties(&child_b);
3025     child_b_id = child_b.GetMetahandle();
3026   }
3027
3028   // Close that transaction.  The above was to setup the initial scenario.  The
3029   // real test starts now.
3030
3031   {
3032     syncable::WriteTransaction trans(
3033         FROM_HERE, syncable::SYNCER, share()->directory.get());
3034
3035     syncable::MutableEntry child_a(&trans, syncable::GET_BY_HANDLE, child_a_id);
3036     syncable::MutableEntry child_b(&trans, syncable::GET_BY_HANDLE, child_b_id);
3037
3038     // Move child A from folder A to folder B and update its position.
3039     child_a.PutParentId(child_b.GetParentId());
3040     child_a.PutPredecessor(child_b.GetId());
3041   }
3042
3043   EXPECT_EQ(1UL, GetChangeListSize());
3044
3045   // Verify that only child a is in the change list.
3046   // (This function will add a failure if the lookup fails.)
3047   FindChangeInList(child_a_id, ChangeRecord::ACTION_UPDATE);
3048 }
3049
3050 // Tests the ordering of deletion changes.
3051 TEST_F(SyncManagerChangeProcessingTest, DeletionsAndChanges) {
3052   int64 type_root = GetIdForDataType(BOOKMARKS);
3053   int64 folder_a_id = kInvalidId;
3054   int64 folder_b_id = kInvalidId;
3055   int64 child_id = kInvalidId;
3056
3057   // Create two folders.  Place a child under folder A.
3058   {
3059     syncable::WriteTransaction trans(
3060         FROM_HERE, syncable::SYNCER, share()->directory.get());
3061     syncable::Entry root(&trans, syncable::GET_BY_HANDLE, type_root);
3062     ASSERT_TRUE(root.good());
3063
3064     syncable::MutableEntry folder_a(&trans, syncable::CREATE,
3065                                     BOOKMARKS, root.GetId(), "folderA");
3066     ASSERT_TRUE(folder_a.good());
3067     SetNodeProperties(&folder_a);
3068     folder_a.PutIsDir(true);
3069     folder_a_id = folder_a.GetMetahandle();
3070
3071     syncable::MutableEntry folder_b(&trans, syncable::CREATE,
3072                                     BOOKMARKS, root.GetId(), "folderB");
3073     ASSERT_TRUE(folder_b.good());
3074     SetNodeProperties(&folder_b);
3075     folder_b.PutIsDir(true);
3076     folder_b_id = folder_b.GetMetahandle();
3077
3078     syncable::MutableEntry child(&trans, syncable::CREATE,
3079                                  BOOKMARKS, folder_a.GetId(),
3080                                  "child");
3081     ASSERT_TRUE(child.good());
3082     SetNodeProperties(&child);
3083     child_id = child.GetMetahandle();
3084   }
3085
3086   // Close that transaction.  The above was to setup the initial scenario.  The
3087   // real test starts now.
3088
3089   {
3090     syncable::WriteTransaction trans(
3091         FROM_HERE, syncable::SYNCER, share()->directory.get());
3092
3093     syncable::MutableEntry folder_a(
3094         &trans, syncable::GET_BY_HANDLE, folder_a_id);
3095     syncable::MutableEntry folder_b(
3096         &trans, syncable::GET_BY_HANDLE, folder_b_id);
3097     syncable::MutableEntry child(&trans, syncable::GET_BY_HANDLE, child_id);
3098
3099     // Delete folder B and its child.
3100     child.PutIsDel(true);
3101     folder_b.PutIsDel(true);
3102
3103     // Make an unrelated change to folder A.
3104     folder_a.PutNonUniqueName("NewNameA");
3105   }
3106
3107   EXPECT_EQ(3UL, GetChangeListSize());
3108
3109   size_t folder_a_pos =
3110       FindChangeInList(folder_a_id, ChangeRecord::ACTION_UPDATE);
3111   size_t folder_b_pos =
3112       FindChangeInList(folder_b_id, ChangeRecord::ACTION_DELETE);
3113   size_t child_pos = FindChangeInList(child_id, ChangeRecord::ACTION_DELETE);
3114
3115   // Deletes should appear before updates.
3116   EXPECT_LT(child_pos, folder_a_pos);
3117   EXPECT_LT(folder_b_pos, folder_a_pos);
3118 }
3119
3120 // During initialization SyncManagerImpl loads sqlite database. If it fails to
3121 // do so it should fail initialization. This test verifies this behavior.
3122 // Test reuses SyncManagerImpl initialization from SyncManagerTest but overrides
3123 // InternalComponentsFactory to return DirectoryBackingStore that always fails
3124 // to load.
3125 class SyncManagerInitInvalidStorageTest : public SyncManagerTest {
3126  public:
3127   SyncManagerInitInvalidStorageTest() {
3128   }
3129
3130   virtual InternalComponentsFactory* GetFactory() OVERRIDE {
3131     return new TestInternalComponentsFactory(GetSwitches(), STORAGE_INVALID);
3132   }
3133 };
3134
3135 // SyncManagerInitInvalidStorageTest::GetFactory will return
3136 // DirectoryBackingStore that ensures that SyncManagerImpl::OpenDirectory fails.
3137 // SyncManagerImpl initialization is done in SyncManagerTest::SetUp. This test's
3138 // task is to ensure that SyncManagerImpl reported initialization failure in
3139 // OnInitializationComplete callback.
3140 TEST_F(SyncManagerInitInvalidStorageTest, FailToOpenDatabase) {
3141   EXPECT_FALSE(initialization_succeeded_);
3142 }
3143
3144 }  // namespace syncer