Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / profile_sync_service_bookmark_unittest.cc
index 44a493f..071efe9 100644 (file)
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/bookmarks/chrome_bookmark_client.h"
+#include "chrome/browser/bookmarks/chrome_bookmark_client_factory.h"
 #include "chrome/browser/sync/glue/bookmark_change_processor.h"
 #include "chrome/browser/sync/glue/bookmark_model_associator.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/bookmarks/core/browser/base_bookmark_model_observer.h"
-#include "components/bookmarks/core/browser/bookmark_model.h"
-#include "components/bookmarks/core/test/bookmark_test_helpers.h"
+#include "components/bookmarks/browser/base_bookmark_model_observer.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/test/bookmark_test_helpers.h"
 #include "components/sync_driver/data_type_error_handler.h"
 #include "components/sync_driver/data_type_error_handler_mock.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "sync/api/sync_error.h"
 #include "sync/internal_api/public/change_record.h"
 #include "sync/internal_api/public/read_node.h"
 
 namespace browser_sync {
 
-using content::BrowserThread;
 using syncer::BaseNode;
 using testing::_;
 using testing::InvokeWithoutArgs;
 using testing::Mock;
 using testing::StrictMock;
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
 static const bool kExpectMobileBookmarks = true;
 #else
 static const bool kExpectMobileBookmarks = false;
-#endif  // defined(OS_ANDROID)
+#endif  // defined(OS_ANDROID) || defined(OS_IOS)
 
 namespace {
 
@@ -228,7 +229,7 @@ class FakeServerChange {
   }
 
   // Pass the fake change list to |service|.
-  void ApplyPendingChanges(ChangeProcessor* processor) {
+  void ApplyPendingChanges(sync_driver::ChangeProcessor* processor) {
     processor->ApplyChangesFromSyncModel(
         trans_, 0, syncer::ImmutableChangeRecordList(&changes_));
   }
@@ -273,22 +274,21 @@ class FakeServerChange {
 
 class ExtensiveChangesBookmarkModelObserver : public BaseBookmarkModelObserver {
  public:
-  explicit ExtensiveChangesBookmarkModelObserver()
+  ExtensiveChangesBookmarkModelObserver()
       : started_count_(0),
         completed_count_at_started_(0),
         completed_count_(0) {}
 
-  virtual void ExtensiveBookmarkChangesBeginning(
-      BookmarkModel* model) OVERRIDE {
+  void ExtensiveBookmarkChangesBeginning(BookmarkModel* model) override {
     ++started_count_;
     completed_count_at_started_ = completed_count_;
   }
 
-  virtual void ExtensiveBookmarkChangesEnded(BookmarkModel* model) OVERRIDE {
+  void ExtensiveBookmarkChangesEnded(BookmarkModel* model) override {
     ++completed_count_;
   }
 
-  virtual void BookmarkModelChanged() OVERRIDE {}
+  void BookmarkModelChanged() override {}
 
   int get_started() const {
     return started_count_;
@@ -318,11 +318,9 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
 
   ProfileSyncServiceBookmarkTest()
       : model_(NULL),
-        ui_thread_(BrowserThread::UI, &message_loop_),
-        file_thread_(BrowserThread::FILE, &message_loop_),
+        thread_bundle_(content::TestBrowserThreadBundle::DEFAULT),
         local_merge_result_(syncer::BOOKMARKS),
-        syncer_merge_result_(syncer::BOOKMARKS) {
-  }
+        syncer_merge_result_(syncer::BOOKMARKS) {}
 
   virtual ~ProfileSyncServiceBookmarkTest() {
     StopSync();
@@ -337,6 +335,10 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
     test_user_share_.TearDown();
   }
 
+  bool CanSyncNode(const BookmarkNode* node) {
+    return model_->client()->CanSyncNode(node);
+  }
+
   // Inserts a folder directly to the share.
   // Do not use this after model association is complete.
   //
@@ -350,7 +352,8 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
 
     // Be sure to call CreatePermanentBookmarkNodes(), otherwise this will fail.
     syncer::ReadNode bookmark_bar(trans);
-    EXPECT_EQ(BaseNode::INIT_OK, bookmark_bar.InitByTagLookup("bookmark_bar"));
+    EXPECT_EQ(BaseNode::INIT_OK,
+              bookmark_bar.InitByTagLookupForBookmarks("bookmark_bar"));
 
     syncer::WriteNode node(trans);
     EXPECT_TRUE(node.InitBookmarkByCreation(bookmark_bar, NULL));
@@ -396,18 +399,17 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
     bool delete_bookmarks = load == DELETE_EXISTING_STORAGE;
     profile_.CreateBookmarkModel(delete_bookmarks);
     model_ = BookmarkModelFactory::GetForProfile(&profile_);
-    test::WaitForBookmarkModelToLoad(model_);
+    bookmarks::test::WaitForBookmarkModelToLoad(model_);
     // This noticeably speeds up the unit tests that request it.
     if (save == DONT_SAVE_TO_STORAGE)
       model_->ClearStore();
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   int GetSyncBookmarkCount() {
     syncer::ReadTransaction trans(FROM_HERE, test_user_share_.user_share());
     syncer::ReadNode node(&trans);
-    if (node.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::BOOKMARKS)) !=
-        syncer::BaseNode::INIT_OK)
+    if (node.InitTypeRoot(syncer::BOOKMARKS) != syncer::BaseNode::INIT_OK)
       return 0;
     return node.GetTotalNodeCount();
   }
@@ -424,8 +426,7 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
       uber_root.InitByRootLookup();
 
       syncer::ReadNode root(&trans);
-      root_exists = (root.InitByTagLookup(syncer::ModelTypeToRootTag(type)) ==
-                     BaseNode::INIT_OK);
+      root_exists = (root.InitTypeRoot(type) == BaseNode::INIT_OK);
     }
 
     if (!root_exists) {
@@ -436,12 +437,18 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
 
     const int kNumPermanentNodes = 3;
     const std::string permanent_tags[kNumPermanentNodes] = {
-      "bookmark_bar", "other_bookmarks", "synced_bookmarks"
+#if defined(OS_IOS)
+      "synced_bookmarks",
+#endif
+      "bookmark_bar",
+      "other_bookmarks",
+#if !defined(OS_IOS)
+      "synced_bookmarks",
+#endif
     };
     syncer::WriteTransaction trans(FROM_HERE, test_user_share_.user_share());
     syncer::ReadNode root(&trans);
-    EXPECT_EQ(BaseNode::INIT_OK, root.InitByTagLookup(
-        syncer::ModelTypeToRootTag(type)));
+    EXPECT_EQ(BaseNode::INIT_OK, root.InitTypeRoot(type));
 
     // Loop through creating permanent nodes as necessary.
     int64 last_child_id = syncer::kInvalidId;
@@ -449,7 +456,7 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
       // First check if the node already exists. This is for tests that involve
       // persistence and set up sync more than once.
       syncer::ReadNode lookup(&trans);
-      if (lookup.InitByTagLookup(permanent_tags[i]) ==
+      if (lookup.InitByTagLookupForBookmarks(permanent_tags[i]) ==
           syncer::ReadNode::INIT_OK) {
         last_child_id = lookup.GetId();
         continue;
@@ -542,7 +549,7 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
     }
     model_associator_.reset();
 
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
 
     // TODO(akalin): Actually close the database and flush it to disk
     // (and make StartSync reload from disk).  This would require
@@ -552,7 +559,7 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
   void UnloadBookmarkModel() {
     profile_.CreateBookmarkModel(false /* delete_bookmarks */);
     model_ = NULL;
-    message_loop_.RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   bool InitSyncNodeFromChromeNode(const BookmarkNode* bnode,
@@ -609,11 +616,14 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
       EXPECT_EQ(gnode.GetPredecessorId(), gprev.GetId());
       EXPECT_EQ(gnode.GetParentId(), gprev.GetParentId());
     }
-    if (browser_index == bnode->parent()->child_count() - 1) {
+    // Note: the managed node is the last child of the root_node but isn't
+    // synced; if CanSyncNode() is false then there is no next node to sync.
+    const BookmarkNode* bnext = NULL;
+    if (browser_index + 1 < bnode->parent()->child_count())
+        bnext = bnode->parent()->GetChild(browser_index + 1);
+    if (!bnext || !CanSyncNode(bnext)) {
       EXPECT_EQ(gnode.GetSuccessorId(), 0);
     } else {
-      const BookmarkNode* bnext =
-          bnode->parent()->GetChild(browser_index + 1);
       syncer::ReadNode gnext(trans);
       ASSERT_TRUE(InitSyncNodeFromChromeNode(bnext, &gnext));
       EXPECT_EQ(gnode.GetSuccessorId(), gnext.GetId());
@@ -634,6 +644,8 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
     const BookmarkNode* bnode =
         model_associator_->GetChromeNodeFromSyncId(sync_id);
     ASSERT_TRUE(bnode);
+    ASSERT_TRUE(CanSyncNode(bnode));
+
     int64 id = model_associator_->GetSyncIdFromChromeId(bnode->id());
     EXPECT_EQ(id, sync_id);
     ExpectSyncerNodeMatching(trans, bnode);
@@ -683,9 +695,15 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
 
   void ExpectModelMatch(syncer::BaseTransaction* trans) {
     const BookmarkNode* root = model_->root_node();
+#if defined(OS_IOS)
+    EXPECT_EQ(root->GetIndexOf(model_->mobile_node()), 0);
+    EXPECT_EQ(root->GetIndexOf(model_->bookmark_bar_node()), 1);
+    EXPECT_EQ(root->GetIndexOf(model_->other_node()), 2);
+#else
     EXPECT_EQ(root->GetIndexOf(model_->bookmark_bar_node()), 0);
     EXPECT_EQ(root->GetIndexOf(model_->other_node()), 1);
     EXPECT_EQ(root->GetIndexOf(model_->mobile_node()), 2);
+#endif
 
     std::stack<int64> stack;
     stack.push(bookmark_bar_id());
@@ -725,23 +743,17 @@ class ProfileSyncServiceBookmarkTest : public testing::Test {
   }
 
  protected:
+  TestingProfile profile_;
   BookmarkModel* model_;
   syncer::TestUserShare test_user_share_;
   scoped_ptr<BookmarkChangeProcessor> change_processor_;
-  StrictMock<DataTypeErrorHandlerMock> mock_error_handler_;
+  StrictMock<sync_driver::DataTypeErrorHandlerMock> mock_error_handler_;
   scoped_ptr<BookmarkModelAssociator> model_associator_;
 
  private:
-  // Used by both |ui_thread_| and |file_thread_|.
-  base::MessageLoop message_loop_;
-  content::TestBrowserThread ui_thread_;
-  // Needed by |model_|.
-  content::TestBrowserThread file_thread_;
-
+  content::TestBrowserThreadBundle thread_bundle_;
   syncer::SyncMergeResult local_merge_result_;
   syncer::SyncMergeResult syncer_merge_result_;
-
-  TestingProfile profile_;
 };
 
 TEST_F(ProfileSyncServiceBookmarkTest, InitialState) {
@@ -1150,7 +1162,7 @@ TEST_F(ProfileSyncServiceBookmarkTest, RepeatedMiddleInsertion) {
 // puts itself into a lame, error state.
 TEST_F(ProfileSyncServiceBookmarkTest, UnrecoverableErrorSuspendsService) {
   EXPECT_CALL(mock_error_handler_,
-              OnSingleDatatypeUnrecoverableError(_, _));
+              OnSingleDataTypeUnrecoverableError(_));
 
   LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
   StartSync();
@@ -1315,6 +1327,11 @@ class ProfileSyncServiceBookmarkTestWithData
   void ExpectBookmarkModelMatchesTestData();
   void WriteTestDataToBookmarkModel();
 
+  // Output transaction versions of |node| and nodes under it to
+  // |node_versions|.
+  void GetTransactionVersions(const BookmarkNode* root,
+                              BookmarkNodeVersionMap* node_versions);
+
   // Verify transaction versions of bookmark nodes and sync nodes are equal
   // recursively. If node is in |version_expected|, versions should match
   // there, too.
@@ -2003,8 +2020,7 @@ TEST_F(ProfileSyncServiceBookmarkTestWithData, UpdateMetaInfoFromModel) {
   ExpectModelMatch();
 }
 
-// Output transaction versions of |node| and nodes under it to |node_versions|.
-void GetTransactionVersions(
+void ProfileSyncServiceBookmarkTestWithData::GetTransactionVersions(
     const BookmarkNode* root,
     BookmarkNodeVersionMap* node_versions) {
   node_versions->clear();
@@ -2018,8 +2034,11 @@ void GetTransactionVersions(
     EXPECT_NE(BookmarkNode::kInvalidSyncTransactionVersion, version);
 
     (*node_versions)[n->id()] = version;
-    for (int i = 0; i < n->child_count(); ++i)
+    for (int i = 0; i < n->child_count(); ++i) {
+      if (!CanSyncNode(n->GetChild(i)))
+        continue;
       nodes.push(n->GetChild(i));
+    }
   }
 }
 
@@ -2136,6 +2155,39 @@ TEST_F(ProfileSyncServiceBookmarkTestWithData, PersistenceError) {
   EXPECT_FALSE(AssociateModels());
 }
 
+// It's possible for update/add calls from the bookmark model to be out of
+// order, or asynchronous. Handle that without triggering an error.
+TEST_F(ProfileSyncServiceBookmarkTest, UpdateThenAdd) {
+  LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
+  StartSync();
+
+  EXPECT_TRUE(other_bookmarks_id());
+  EXPECT_TRUE(bookmark_bar_id());
+  EXPECT_TRUE(mobile_bookmarks_id());
+
+  ExpectModelMatch();
+
+  // Now destroy the change processor then add a bookmark, to simulate
+  // missing the Update call.
+  change_processor_.reset();
+  const BookmarkNode* node = model_->AddURL(model_->bookmark_bar_node(),
+                                            0,
+                                            base::ASCIIToUTF16("title"),
+                                            GURL("http://www.url.com"));
+
+  // Recreate the change processor then update that bookmark. Sync should
+  // receive the update call and gracefully treat that as if it were an add.
+  change_processor_.reset(new BookmarkChangeProcessor(
+      &profile_, model_associator_.get(), &mock_error_handler_));
+  change_processor_->Start(test_user_share_.user_share());
+  model_->SetTitle(node, base::ASCIIToUTF16("title2"));
+  ExpectModelMatch();
+
+  // Then simulate the add call arriving late.
+  change_processor_->BookmarkNodeAdded(model_, model_->bookmark_bar_node(), 0);
+  ExpectModelMatch();
+}
+
 }  // namespace
 
 }  // namespace browser_sync