// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/basictypes.h" #include "sync/engine/process_updates_command.h" #include "sync/engine/syncer_proto_util.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/test/test_entry_factory.h" #include "sync/sessions/sync_session.h" #include "sync/syncable/mutable_entry.h" #include "sync/syncable/syncable_id.h" #include "sync/syncable/syncable_proto_util.h" #include "sync/syncable/syncable_read_transaction.h" #include "sync/syncable/syncable_write_transaction.h" #include "sync/test/engine/fake_model_worker.h" #include "sync/test/engine/syncer_command_test.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { using sync_pb::SyncEntity; using syncable::Id; using syncable::MutableEntry; using syncable::UNITTEST; using syncable::WriteTransaction; namespace { class ProcessUpdatesCommandTest : public SyncerCommandTest { protected: ProcessUpdatesCommandTest() {} virtual ~ProcessUpdatesCommandTest() {} virtual void SetUp() { workers()->push_back( make_scoped_refptr(new FakeModelWorker(GROUP_UI))); workers()->push_back( make_scoped_refptr(new FakeModelWorker(GROUP_DB))); (*mutable_routing_info())[PREFERENCES] = GROUP_UI; (*mutable_routing_info())[BOOKMARKS] = GROUP_UI; (*mutable_routing_info())[AUTOFILL] = GROUP_DB; SyncerCommandTest::SetUp(); test_entry_factory_.reset(new TestEntryFactory(directory())); } void CreateLocalItem(const std::string& item_id, const std::string& parent_id, const ModelType& type) { WriteTransaction trans(FROM_HERE, UNITTEST, directory()); MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM, Id::CreateFromServerId(item_id)); ASSERT_TRUE(entry.good()); entry.Put(syncable::BASE_VERSION, 1); entry.Put(syncable::SERVER_VERSION, 1); entry.Put(syncable::NON_UNIQUE_NAME, item_id); entry.Put(syncable::PARENT_ID, Id::CreateFromServerId(parent_id)); sync_pb::EntitySpecifics default_specifics; AddDefaultFieldValue(type, &default_specifics); entry.Put(syncable::SERVER_SPECIFICS, default_specifics); } SyncEntity* AddUpdate(sync_pb::GetUpdatesResponse* updates, const std::string& id, const std::string& parent, const ModelType& type) { sync_pb::SyncEntity* e = updates->add_entries(); e->set_id_string(id); e->set_parent_id_string(parent); e->set_non_unique_name(id); e->set_name(id); e->set_version(1000); AddDefaultFieldValue(type, e->mutable_specifics()); return e; } ProcessUpdatesCommand command_; scoped_ptr test_entry_factory_; private: DISALLOW_COPY_AND_ASSIGN(ProcessUpdatesCommandTest); }; TEST_F(ProcessUpdatesCommandTest, GroupsToChange) { std::string root = syncable::GetNullId().GetServerId(); CreateLocalItem("p1", root, PREFERENCES); CreateLocalItem("a1", root, AUTOFILL); ExpectNoGroupsToChange(command_); sync_pb::GetUpdatesResponse* updates = session()->mutable_status_controller()-> mutable_updates_response()->mutable_get_updates(); AddUpdate(updates, "p1", root, PREFERENCES); AddUpdate(updates, "a1", root, AUTOFILL); ExpectGroupsToChange(command_, GROUP_UI, GROUP_DB); command_.ExecuteImpl(session()); } static const char kCacheGuid[] = "IrcjZ2jyzHDV9Io4+zKcXQ=="; // Test that the bookmark tag is set on newly downloaded items. TEST_F(ProcessUpdatesCommandTest, NewBookmarkTag) { std::string root = syncable::GetNullId().GetServerId(); sync_pb::GetUpdatesResponse* updates = session()->mutable_status_controller()-> mutable_updates_response()->mutable_get_updates(); Id server_id = Id::CreateFromServerId("b1"); SyncEntity* e = AddUpdate(updates, SyncableIdToProto(server_id), root, BOOKMARKS); e->set_originator_cache_guid( std::string(kCacheGuid, arraysize(kCacheGuid)-1)); Id client_id = Id::CreateFromClientString("-2"); e->set_originator_client_item_id(client_id.GetServerId()); e->set_position_in_parent(0); command_.ExecuteImpl(session()); syncable::ReadTransaction trans(FROM_HERE, directory()); syncable::Entry entry(&trans, syncable::GET_BY_ID, server_id); ASSERT_TRUE(entry.good()); EXPECT_TRUE( UniquePosition::IsValidSuffix(entry.Get(syncable::UNIQUE_BOOKMARK_TAG))); EXPECT_TRUE(entry.Get(syncable::SERVER_UNIQUE_POSITION).IsValid()); // If this assertion fails, that might indicate that the algorithm used to // generate bookmark tags has been modified. This could have implications for // bookmark ordering. Please make sure you know what you're doing if you // intend to make such a change. EXPECT_EQ("6wHRAb3kbnXV5GHrejp4/c1y5tw=", entry.Get(syncable::UNIQUE_BOOKMARK_TAG)); } TEST_F(ProcessUpdatesCommandTest, ReceiveServerCreatedBookmarkFolders) { Id server_id = Id::CreateFromServerId("xyz"); std::string root = syncable::GetNullId().GetServerId(); sync_pb::GetUpdatesResponse* updates = session()->mutable_status_controller()-> mutable_updates_response()->mutable_get_updates(); // Create an update that mimics the bookmark root. SyncEntity* e = AddUpdate(updates, SyncableIdToProto(server_id), root, BOOKMARKS); e->set_server_defined_unique_tag("google_chrome_bookmarks"); e->set_folder(true); EXPECT_FALSE(SyncerProtoUtil::ShouldMaintainPosition(*e)); command_.ExecuteImpl(session()); syncable::ReadTransaction trans(FROM_HERE, directory()); syncable::Entry entry(&trans, syncable::GET_BY_ID, server_id); ASSERT_TRUE(entry.good()); EXPECT_FALSE(entry.ShouldMaintainPosition()); EXPECT_FALSE(entry.Get(syncable::UNIQUE_POSITION).IsValid()); EXPECT_FALSE(entry.Get(syncable::SERVER_UNIQUE_POSITION).IsValid()); EXPECT_TRUE(entry.Get(syncable::UNIQUE_BOOKMARK_TAG).empty()); } TEST_F(ProcessUpdatesCommandTest, ReceiveNonBookmarkItem) { Id server_id = Id::CreateFromServerId("xyz"); std::string root = syncable::GetNullId().GetServerId(); sync_pb::GetUpdatesResponse* updates = session()->mutable_status_controller()-> mutable_updates_response()->mutable_get_updates(); SyncEntity* e = AddUpdate(updates, SyncableIdToProto(server_id), root, AUTOFILL); e->set_server_defined_unique_tag("9PGRuKdX5sHyGMB17CvYTXuC43I="); EXPECT_FALSE(SyncerProtoUtil::ShouldMaintainPosition(*e)); command_.ExecuteImpl(session()); syncable::ReadTransaction trans(FROM_HERE, directory()); syncable::Entry entry(&trans, syncable::GET_BY_ID, server_id); ASSERT_TRUE(entry.good()); EXPECT_FALSE(entry.ShouldMaintainPosition()); EXPECT_FALSE(entry.Get(syncable::UNIQUE_POSITION).IsValid()); EXPECT_FALSE(entry.Get(syncable::SERVER_UNIQUE_POSITION).IsValid()); EXPECT_TRUE(entry.Get(syncable::UNIQUE_BOOKMARK_TAG).empty()); } } // namespace } // namespace syncer