1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file. 41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "sync/engine/directory_update_handler.h" 61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/compiler_specific.h" 81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/message_loop/message_loop.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/stl_util.h" 101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/engine/syncer_proto_util.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "sync/internal_api/public/base/attachment_id_proto.h" 121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/internal_api/public/base/model_type.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "sync/internal_api/public/test/test_entry_factory.h" 141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/protocol/sync.pb.h" 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "sync/sessions/directory_type_debug_info_emitter.h" 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/sessions/status_controller.h" 171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/syncable/directory.h" 181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/syncable/entry.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "sync/syncable/mutable_entry.h" 201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/syncable/syncable_model_neutral_write_transaction.h" 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/syncable/syncable_proto_util.h" 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/syncable/syncable_read_transaction.h" 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "sync/syncable/syncable_write_transaction.h" 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "sync/test/engine/fake_model_worker.h" 251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/test/engine/test_directory_setter_upper.h" 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "sync/test/engine/test_id_factory.h" 271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/test/engine/test_syncable_utils.h" 281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace syncer { 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using syncable::UNITTEST; 331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static const int64 kDefaultVersion = 1000; 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A test harness for tests that focus on processing updates. 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Update processing is what occurs when we first download updates. It converts 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// the received protobuf message into information in the syncable::Directory. 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Any invalid or redundant updates will be dropped at this point. 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class DirectoryUpdateHandlerProcessUpdateTest : public ::testing::Test { 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public: 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DirectoryUpdateHandlerProcessUpdateTest() 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : ui_worker_(new FakeModelWorker(GROUP_UI)) { 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual ~DirectoryUpdateHandlerProcessUpdateTest() {} 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual void SetUp() OVERRIDE { 501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) dir_maker_.SetUp(); 511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual void TearDown() OVERRIDE { 541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) dir_maker_.TearDown(); 551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::Directory* dir() { 581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return dir_maker_.directory(); 591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) protected: 621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<sync_pb::SyncEntity> CreateUpdate( 631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& id, 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& parent, 651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const ModelType& type); 661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // This exists mostly to give tests access to the protected member function. 681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Warning: This takes the syncable directory lock. 691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void UpdateSyncEntities( 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DirectoryUpdateHandler* handler, 711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const SyncEntityList& applicable_updates, 721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sessions::StatusController* status); 731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Another function to access private member functions. 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void UpdateProgressMarkers( 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DirectoryUpdateHandler* handler, 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const sync_pb::DataTypeProgressMarker& progress); 781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<FakeModelWorker> ui_worker() { 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return ui_worker_; 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool EntryExists(const std::string& id) { 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, dir()); 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) syncable::Entry e(&trans, syncable::GET_BY_ID, 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) syncable::Id::CreateFromServerId(id)); 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return e.good() && !e.GetIsDel(); 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) protected: 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Used in the construction of DirectoryTypeDebugInfoEmitters. 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ObserverList<TypeDebugInfoObserver> type_observers_; 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private: 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::MessageLoop loop_; // Needed to initialize the directory. 961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TestDirectorySetterUpper dir_maker_; 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<FakeModelWorker> ui_worker_; 981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)scoped_ptr<sync_pb::SyncEntity> 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)DirectoryUpdateHandlerProcessUpdateTest::CreateUpdate( 1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& id, 1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& parent, 1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const ModelType& type) { 1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<sync_pb::SyncEntity> e(new sync_pb::SyncEntity()); 1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_id_string(id); 1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_parent_id_string(parent); 1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_non_unique_name(id); 1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_name(id); 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) e->set_version(kDefaultVersion); 1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) AddDefaultFieldValue(type, e->mutable_specifics()); 1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return e.Pass(); 1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void DirectoryUpdateHandlerProcessUpdateTest::UpdateSyncEntities( 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DirectoryUpdateHandler* handler, 1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const SyncEntityList& applicable_updates, 1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sessions::StatusController* status) { 1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::ModelNeutralWriteTransaction trans(FROM_HERE, UNITTEST, dir()); 1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) handler->UpdateSyncEntities(&trans, applicable_updates, status); 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void DirectoryUpdateHandlerProcessUpdateTest::UpdateProgressMarkers( 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DirectoryUpdateHandler* handler, 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const sync_pb::DataTypeProgressMarker& progress) { 1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) handler->UpdateProgressMarker(progress); 1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static const char kCacheGuid[] = "IrcjZ2jyzHDV9Io4+zKcXQ=="; 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Test that the bookmark tag is set on newly downloaded items. 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerProcessUpdateTest, NewBookmarkTag) { 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DirectoryTypeDebugInfoEmitter emitter(BOOKMARKS, &type_observers_); 134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DirectoryUpdateHandler handler(dir(), BOOKMARKS, ui_worker(), &emitter); 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sync_pb::GetUpdatesResponse gu_response; 1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sessions::StatusController status; 1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Add a bookmark item to the update message. 1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string root = syncable::GetNullId().GetServerId(); 1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::Id server_id = syncable::Id::CreateFromServerId("b1"); 1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<sync_pb::SyncEntity> e = 1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateUpdate(SyncableIdToProto(server_id), root, BOOKMARKS); 1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_originator_cache_guid( 1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string(kCacheGuid, arraysize(kCacheGuid)-1)); 1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::Id client_id = syncable::Id::CreateFromClientString("-2"); 1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_originator_client_item_id(client_id.GetServerId()); 1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_position_in_parent(0); 1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Add it to the applicable updates list. 1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SyncEntityList bookmark_updates; 1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bookmark_updates.push_back(e.get()); 1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Process the update. 1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UpdateSyncEntities(&handler, bookmark_updates, &status); 1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, dir()); 1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::Entry entry(&trans, syncable::GET_BY_ID, server_id); 1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(entry.good()); 1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(UniquePosition::IsValidSuffix(entry.GetUniqueBookmarkTag())); 1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(entry.GetServerUniquePosition().IsValid()); 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // If this assertion fails, that might indicate that the algorithm used to 1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // generate bookmark tags has been modified. This could have implications for 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // bookmark ordering. Please make sure you know what you're doing if you 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // intend to make such a change. 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ("6wHRAb3kbnXV5GHrejp4/c1y5tw=", entry.GetUniqueBookmarkTag()); 1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Test the receipt of a type root node. 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerProcessUpdateTest, 171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ReceiveServerCreatedBookmarkFolders) { 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DirectoryTypeDebugInfoEmitter emitter(BOOKMARKS, &type_observers_); 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DirectoryUpdateHandler handler(dir(), BOOKMARKS, ui_worker(), &emitter); 1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sync_pb::GetUpdatesResponse gu_response; 1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sessions::StatusController status; 1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Create an update that mimics the bookmark root. 1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::Id server_id = syncable::Id::CreateFromServerId("xyz"); 1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string root = syncable::GetNullId().GetServerId(); 1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<sync_pb::SyncEntity> e = 1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateUpdate(SyncableIdToProto(server_id), root, BOOKMARKS); 1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_server_defined_unique_tag("google_chrome_bookmarks"); 1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_folder(true); 1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Add it to the applicable updates list. 1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SyncEntityList bookmark_updates; 1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bookmark_updates.push_back(e.get()); 1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(SyncerProtoUtil::ShouldMaintainPosition(*e)); 1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Process it. 1921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UpdateSyncEntities(&handler, bookmark_updates, &status); 1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Verify the results. 1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, dir()); 1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::Entry entry(&trans, syncable::GET_BY_ID, server_id); 1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(entry.good()); 1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(entry.ShouldMaintainPosition()); 2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(entry.GetUniquePosition().IsValid()); 2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(entry.GetServerUniquePosition().IsValid()); 2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(entry.GetUniqueBookmarkTag().empty()); 2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Test the receipt of a non-bookmark item. 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ReceiveNonBookmarkItem) { 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DirectoryTypeDebugInfoEmitter emitter(AUTOFILL, &type_observers_); 208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DirectoryUpdateHandler handler(dir(), AUTOFILL, ui_worker(), &emitter); 2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sync_pb::GetUpdatesResponse gu_response; 2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sessions::StatusController status; 2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string root = syncable::GetNullId().GetServerId(); 2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::Id server_id = syncable::Id::CreateFromServerId("xyz"); 2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<sync_pb::SyncEntity> e = 215a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CreateUpdate(SyncableIdToProto(server_id), root, AUTOFILL); 2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e->set_server_defined_unique_tag("9PGRuKdX5sHyGMB17CvYTXuC43I="); 2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Add it to the applicable updates list. 2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SyncEntityList autofill_updates; 2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) autofill_updates.push_back(e.get()); 2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(SyncerProtoUtil::ShouldMaintainPosition(*e)); 2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Process it. 2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UpdateSyncEntities(&handler, autofill_updates, &status); 2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, dir()); 2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) syncable::Entry entry(&trans, syncable::GET_BY_ID, server_id); 2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(entry.good()); 2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(entry.ShouldMaintainPosition()); 2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(entry.GetUniquePosition().IsValid()); 2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(entry.GetServerUniquePosition().IsValid()); 2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(entry.GetUniqueBookmarkTag().empty()); 2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Tests the setting of progress markers. 238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ProcessNewProgressMarkers) { 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DirectoryTypeDebugInfoEmitter emitter(BOOKMARKS, &type_observers_); 240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DirectoryUpdateHandler handler(dir(), BOOKMARKS, ui_worker(), &emitter); 2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sync_pb::DataTypeProgressMarker progress; 2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) progress.set_data_type_id(GetSpecificsFieldNumberFromModelType(BOOKMARKS)); 2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) progress.set_token("token"); 2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UpdateProgressMarkers(&handler, progress); 2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sync_pb::DataTypeProgressMarker saved; 2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) dir()->GetDownloadProgress(BOOKMARKS, &saved); 2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(progress.token(), saved.token()); 2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(progress.data_type_id(), saved.data_type_id()); 2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByVersion) { 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_); 257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, 258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui_worker(), &emitter); 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sessions::StatusController status; 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sync_pb::DataTypeProgressMarker progress; 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) progress.set_data_type_id( 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); 264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) progress.set_token("token"); 265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 10); 266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch sync_pb::DataTypeContext context; 268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch context.set_data_type_id( 269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); 270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch context.set_context("context"); 271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch context.set_version(1); 272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<sync_pb::SyncEntity> type_root = 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("root")), 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) syncable::GetNullId().GetServerId(), 276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SYNCED_NOTIFICATIONS); 277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type_root->set_server_defined_unique_tag( 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ModelTypeToRootTag(SYNCED_NOTIFICATIONS)); 279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type_root->set_folder(true); 280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<sync_pb::SyncEntity> e1 = 282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("e1")), 283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type_root->id_string(), 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SYNCED_NOTIFICATIONS); 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<sync_pb::SyncEntity> e2 = 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("e2")), 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type_root->id_string(), 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SYNCED_NOTIFICATIONS); 290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) e2->set_version(kDefaultVersion + 100); 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Add to the applicable updates list. 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SyncEntityList updates; 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) updates.push_back(type_root.get()); 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) updates.push_back(e1.get()); 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) updates.push_back(e2.get()); 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Process and apply updates. 299a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_EQ( 300a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch SYNCER_OK, 301a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch handler.ProcessGetUpdatesResponse(progress, context, updates, &status)); 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handler.ApplyUpdates(&status); 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Verify none is deleted because they are unapplied during GC. 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(EntryExists(type_root->id_string())); 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(EntryExists(e1->id_string())); 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(EntryExists(e2->id_string())); 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Process and apply again. Old entry is deleted but not root. 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 20); 311a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_EQ(SYNCER_OK, 312a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch handler.ProcessGetUpdatesResponse( 313a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch progress, context, SyncEntityList(), &status)); 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handler.ApplyUpdates(&status); 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(EntryExists(type_root->id_string())); 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_FALSE(EntryExists(e1->id_string())); 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(EntryExists(e2->id_string())); 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 320a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochTEST_F(DirectoryUpdateHandlerProcessUpdateTest, ContextVersion) { 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_); 322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, 323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui_worker(), &emitter); 324a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch sessions::StatusController status; 325a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch int field_number = GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS); 326a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 327a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch sync_pb::DataTypeProgressMarker progress; 328a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch progress.set_data_type_id( 329a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); 330a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch progress.set_token("token"); 331a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 332a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch sync_pb::DataTypeContext old_context; 333a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch old_context.set_version(1); 334a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch old_context.set_context("data"); 335a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch old_context.set_data_type_id(field_number); 336a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 337a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch scoped_ptr<sync_pb::SyncEntity> type_root = 338a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("root")), 339a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch syncable::GetNullId().GetServerId(), 340a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch SYNCED_NOTIFICATIONS); 341a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch type_root->set_server_defined_unique_tag( 342a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ModelTypeToRootTag(SYNCED_NOTIFICATIONS)); 343a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch type_root->set_folder(true); 344a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch scoped_ptr<sync_pb::SyncEntity> e1 = 345a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("e1")), 346a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch type_root->id_string(), 347a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch SYNCED_NOTIFICATIONS); 348a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 349a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch SyncEntityList updates; 350a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch updates.push_back(type_root.get()); 351a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch updates.push_back(e1.get()); 352a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 353a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // The first response should be processed fine. 354a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_EQ(SYNCER_OK, 355a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch handler.ProcessGetUpdatesResponse( 356a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch progress, old_context, updates, &status)); 357a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch handler.ApplyUpdates(&status); 358a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 359a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_TRUE(EntryExists(type_root->id_string())); 360a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_TRUE(EntryExists(e1->id_string())); 361a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 362a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch { 363a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch sync_pb::DataTypeContext dir_context; 364a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch syncable::ReadTransaction trans(FROM_HERE, dir()); 365a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch trans.directory()->GetDataTypeContext( 366a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch &trans, SYNCED_NOTIFICATIONS, &dir_context); 367a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString()); 368a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 369a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 370a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch sync_pb::DataTypeContext new_context; 371a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch new_context.set_version(0); 372a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch new_context.set_context("old"); 373a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch new_context.set_data_type_id(field_number); 374a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 375a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch scoped_ptr<sync_pb::SyncEntity> e2 = 376a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("e2")), 377a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch type_root->id_string(), 378a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch SYNCED_NOTIFICATIONS); 379a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch updates.clear(); 380a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch updates.push_back(e2.get()); 381a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 382a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // The second response, with an old context version, should result in an 383a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // error and the updates should be dropped. 384a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_EQ(DATATYPE_TRIGGERED_RETRY, 385a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch handler.ProcessGetUpdatesResponse( 386a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch progress, new_context, updates, &status)); 387a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch handler.ApplyUpdates(&status); 388a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 389a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_FALSE(EntryExists(e2->id_string())); 390a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 391a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch { 392a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch sync_pb::DataTypeContext dir_context; 393a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch syncable::ReadTransaction trans(FROM_HERE, dir()); 394a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch trans.directory()->GetDataTypeContext( 395a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch &trans, SYNCED_NOTIFICATIONS, &dir_context); 396a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString()); 397a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 398a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 399a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// See that updates containing attachment metadata are applied 401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// (i.e. server_attachment_metadata is copied to attachment_metadata). 402116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(DirectoryUpdateHandlerProcessUpdateTest, 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ProcessAndApplyUpdatesWithAttachments) { 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DirectoryTypeDebugInfoEmitter emitter(ARTICLES, &type_observers_); 405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DirectoryUpdateHandler handler(dir(), ARTICLES, ui_worker(), &emitter); 406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sessions::StatusController status; 407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::DataTypeProgressMarker progress; 409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch progress.set_data_type_id(GetSpecificsFieldNumberFromModelType(ARTICLES)); 410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch progress.set_token("token"); 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 10); 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::DataTypeContext context; 414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch context.set_data_type_id(GetSpecificsFieldNumberFromModelType(ARTICLES)); 415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch context.set_context("context"); 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch context.set_version(1); 417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<sync_pb::SyncEntity> type_root = 419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("root")), 420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch syncable::GetNullId().GetServerId(), 421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ARTICLES); 422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch type_root->set_server_defined_unique_tag(ModelTypeToRootTag(ARTICLES)); 423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch type_root->set_folder(true); 424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<sync_pb::SyncEntity> e1 = 426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("e1")), 427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch type_root->id_string(), 428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ARTICLES); 429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentIdProto* attachment_id = e1->add_attachment_id(); 430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *attachment_id = CreateAttachmentIdProto(); 431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SyncEntityList updates; 433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch updates.push_back(type_root.get()); 434116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch updates.push_back(e1.get()); 435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Process and apply updates. 437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ( 438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SYNCER_OK, 439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch handler.ProcessGetUpdatesResponse(progress, context, updates, &status)); 440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch handler.ApplyUpdates(&status); 441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ASSERT_TRUE(EntryExists(type_root->id_string())); 443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ASSERT_TRUE(EntryExists(e1->id_string())); 444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch { 445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch syncable::ReadTransaction trans(FROM_HERE, dir()); 446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch syncable::Entry e(&trans, 447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch syncable::GET_BY_ID, 448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch syncable::Id::CreateFromServerId(e1->id_string())); 449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // See that the attachment_metadata is correct. 451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentMetadata attachment_metadata = e.GetAttachmentMetadata(); 452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ASSERT_EQ(1, attachment_metadata.record_size()); 453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ASSERT_EQ(attachment_id->SerializeAsString(), 454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch attachment_metadata.record(0).id().SerializeAsString()); 455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ASSERT_TRUE(attachment_metadata.record(0).is_on_server()); 456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 457116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // See that attachment_metadata and server_attachment_metadata are equal. 458116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ASSERT_EQ(attachment_metadata.SerializeAsString(), 459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch e.GetServerAttachmentMetadata().SerializeAsString()); 460116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A test harness for tests that focus on applying updates. 464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// 465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Update application is performed when we want to take updates that were 466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// previously downloaded, processed, and stored in our syncable::Directory 467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// and use them to update our local state (both the Directory's local state 468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// and the model's local state, though these tests focus only on the Directory's 469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// local state). 470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// 471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// This is kept separate from the update processing test in part for historical 472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// reasons, and in part because these tests may require a bit more infrastrcture 473a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// in the future. Update application should happen on a different thread a lot 474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// of the time so these tests may end up requiring more infrastructure than the 475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// update processing tests. Currently, we're bypassing most of those issues by 476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// using FakeModelWorkers, so there's not much difference between the two test 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// harnesses. 478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class DirectoryUpdateHandlerApplyUpdateTest : public ::testing::Test { 479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DirectoryUpdateHandlerApplyUpdateTest() 481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : ui_worker_(new FakeModelWorker(GROUP_UI)), 482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) password_worker_(new FakeModelWorker(GROUP_PASSWORD)), 483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) passive_worker_(new FakeModelWorker(GROUP_PASSIVE)), 484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bookmarks_emitter_(BOOKMARKS, &type_observers_), 485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) passwords_emitter_(PASSWORDS, &type_observers_), 486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch articles_emitter_(ARTICLES, &type_observers_), 487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) update_handler_map_deleter_(&update_handler_map_) {} 488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual void SetUp() OVERRIDE { 490a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dir_maker_.SetUp(); 491a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory_.reset(new TestEntryFactory(directory())); 492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 493a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) update_handler_map_.insert(std::make_pair( 494a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BOOKMARKS, 495010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) new DirectoryUpdateHandler(directory(), BOOKMARKS, 496010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui_worker_, &bookmarks_emitter_))); 497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) update_handler_map_.insert(std::make_pair( 498a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) PASSWORDS, 499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new DirectoryUpdateHandler(directory(), 500010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) PASSWORDS, 501010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) password_worker_, 502010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) &passwords_emitter_))); 503116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch update_handler_map_.insert(std::make_pair( 504116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ARTICLES, 505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new DirectoryUpdateHandler( 506116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch directory(), ARTICLES, ui_worker_, &articles_emitter_))); 507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 508a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual void TearDown() OVERRIDE { 510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dir_maker_.TearDown(); 511a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& GetBookmarksUpdateCounters() { 514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return bookmarks_emitter_.GetUpdateCounters(); 515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& GetPasswordsUpdateCounters() { 518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return passwords_emitter_.GetUpdateCounters(); 519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const UpdateCounters& GetArticlesUpdateCounters() { 522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return articles_emitter_.GetUpdateCounters(); 523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) protected: 526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void ApplyBookmarkUpdates(sessions::StatusController* status) { 527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) update_handler_map_[BOOKMARKS]->ApplyUpdates(status); 528a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 529a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void ApplyPasswordUpdates(sessions::StatusController* status) { 531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) update_handler_map_[PASSWORDS]->ApplyUpdates(status); 532a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 534116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void ApplyArticlesUpdates(sessions::StatusController* status) { 535116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch update_handler_map_[ARTICLES]->ApplyUpdates(status); 536116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 537116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TestEntryFactory* entry_factory() { 539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return entry_factory_.get(); 540a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 541a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 542a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Directory* directory() { 543a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return dir_maker_.directory(); 544a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 545a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 546a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typedef std::map<ModelType, UpdateHandler*> UpdateHandlerMap; 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::MessageLoop loop_; // Needed to initialize the directory. 550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TestDirectorySetterUpper dir_maker_; 551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<TestEntryFactory> entry_factory_; 552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<FakeModelWorker> ui_worker_; 554a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<FakeModelWorker> password_worker_; 555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<FakeModelWorker> passive_worker_; 556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ObserverList<TypeDebugInfoObserver> type_observers_; 558010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DirectoryTypeDebugInfoEmitter bookmarks_emitter_; 559010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DirectoryTypeDebugInfoEmitter passwords_emitter_; 560116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DirectoryTypeDebugInfoEmitter articles_emitter_; 561010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 562a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UpdateHandlerMap update_handler_map_; 563a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) STLValueDeleter<UpdateHandlerMap> update_handler_map_deleter_; 564a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 565a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 566a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 567a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)sync_pb::EntitySpecifics DefaultBookmarkSpecifics() { 568a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::EntitySpecifics result; 569a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddDefaultFieldValue(BOOKMARKS, &result); 570a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return result; 571a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 572a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 573a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 574a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Test update application for a few bookmark items. 575a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SimpleBookmark) { 576a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 577a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 578a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string root_server_id = syncable::GetNullId().GetServerId(); 579a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 parent_handle = 580a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnappliedNewBookmarkItemWithParent( 581a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "parent", DefaultBookmarkSpecifics(), root_server_id); 582a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 child_handle = 583a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnappliedNewBookmarkItemWithParent( 584a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "child", DefaultBookmarkSpecifics(), "parent"); 585a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 586a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status); 587a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counter = GetBookmarksUpdateCounters(); 589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0, counter.num_encryption_conflict_application_failures) 590a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "Simple update shouldn't result in conflicts"; 591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0, counter.num_hierarchy_conflict_application_failures) 592a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "Simple update shouldn't result in conflicts"; 593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(2, counter.num_updates_applied) 594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "All items should have been successfully applied"; 595a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 596a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 597a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 598a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 599a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry parent(&trans, syncable::GET_BY_HANDLE, parent_handle); 600a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry child(&trans, syncable::GET_BY_HANDLE, child_handle); 601a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 602a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(parent.good()); 603a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(child.good()); 604a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 605a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(parent.GetIsUnsynced()); 606a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(parent.GetIsUnappliedUpdate()); 607a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(child.GetIsUnsynced()); 608a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(child.GetIsUnappliedUpdate()); 609a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 610a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 611a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 612a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Test that the applicator can handle updates delivered out of order. 613a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, 614a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BookmarkChildrenBeforeParent) { 615a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Start with some bookmarks whose parents are unknown. 616a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string root_server_id = syncable::GetNullId().GetServerId(); 617a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 a_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( 618a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "a_child_created_first", DefaultBookmarkSpecifics(), "parent"); 619a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 x_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( 620a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "x_child_created_first", DefaultBookmarkSpecifics(), "parent"); 621a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 622a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Update application will fail. 623a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status1; 624a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status1); 625a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(0, status1.num_updates_applied()); 626a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(2, status1.num_hierarchy_conflicts()); 627a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 628a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 629a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 630a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 631a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry a(&trans, syncable::GET_BY_HANDLE, a_handle); 632a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry x(&trans, syncable::GET_BY_HANDLE, x_handle); 633a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 634a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(a.good()); 635a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(x.good()); 636a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 637a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(a.GetIsUnappliedUpdate()); 638a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(x.GetIsUnappliedUpdate()); 639a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 640a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 641a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Now add their parent and a few siblings. 642a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnappliedNewBookmarkItemWithParent( 643a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "parent", DefaultBookmarkSpecifics(), root_server_id); 644a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnappliedNewBookmarkItemWithParent( 645a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "a_child_created_second", DefaultBookmarkSpecifics(), "parent"); 646a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnappliedNewBookmarkItemWithParent( 647a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "x_child_created_second", DefaultBookmarkSpecifics(), "parent"); 648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 649a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Update application will succeed. 650a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status2; 651a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status2); 652a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(5, status2.num_updates_applied()) 653a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "All updates should have been successfully applied"; 654a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 655a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 656a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 657a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 658a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry a(&trans, syncable::GET_BY_HANDLE, a_handle); 659a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry x(&trans, syncable::GET_BY_HANDLE, x_handle); 660a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 661a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(a.good()); 662a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(x.good()); 663a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 664a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(a.GetIsUnappliedUpdate()); 665a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(x.GetIsUnappliedUpdate()); 666a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 667a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 668a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 669a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Try to apply changes on an item that is both IS_UNSYNCED and 670a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// IS_UNAPPLIED_UPDATE. Conflict resolution should be performed. 671a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SimpleBookmarkConflict) { 672a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 handle = entry_factory()->CreateUnappliedAndUnsyncedBookmarkItem("x"); 673a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 674a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int original_server_version = -10; 675a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 676a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 677a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); 678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) original_server_version = e.GetServerVersion(); 679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_NE(original_server_version, e.GetBaseVersion()); 680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(e.GetIsUnsynced()); 681a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 682a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 683a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 684a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status); 685cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 686cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counters = GetBookmarksUpdateCounters(); 687cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1, counters.num_server_overwrites) 688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "Unsynced and unapplied item conflict should be resolved"; 689cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0, counters.num_updates_applied) 690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "Update should not be applied; we should override the server."; 691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 692a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); 695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(e.good()); 696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(original_server_version, e.GetServerVersion()); 697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(original_server_version, e.GetBaseVersion()); 698a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(e.GetIsUnappliedUpdate()); 699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The unsynced flag will remain set until we successfully commit the item. 701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(e.GetIsUnsynced()); 702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 704a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 705a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Create a simple conflict that is also a hierarchy conflict. If we were to 706a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// follow the normal "server wins" logic, we'd end up violating hierarchy 707a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// constraints. The hierarchy conflict must take precedence. We can not allow 708a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// the update to be applied. The item must remain in the conflict state. 709a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, HierarchyAndSimpleConflict) { 710a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create a simply-conflicting item. It will start with valid parent ids. 711a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 handle = entry_factory()->CreateUnappliedAndUnsyncedBookmarkItem( 712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "orphaned_by_server"); 713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 714a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Manually set the SERVER_PARENT_ID to bad value. 715a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // A bad parent indicates a hierarchy conflict. 716a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); 717a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); 718a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(entry.good()); 719a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 720a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.PutServerParentId(TestIdFactory::MakeServer("bogus_parent")); 721a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 722a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 723a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 724a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status); 725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counters = GetBookmarksUpdateCounters(); 727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0, counters.num_updates_applied); 728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0, counters.num_server_overwrites); 729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); 730a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 731a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 732a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 733a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); 734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(e.good()); 735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(e.GetIsUnappliedUpdate()); 736a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(e.GetIsUnsynced()); 737a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 738a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 739a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 740a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Attempt to apply an udpate that would create a bookmark folder loop. This 741a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// application should fail. 742a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, BookmarkFolderLoop) { 743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Item 'X' locally has parent of 'root'. Server is updating it to have 744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // parent of 'Y'. 745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 746a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create it as a child of root node. 747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 handle = entry_factory()->CreateSyncedItem("X", BOOKMARKS, true); 748a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 750a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); 751a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); 752a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(entry.good()); 753a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 754a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Re-parent from root to "Y" 755a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.PutServerVersion(entry_factory()->GetNextRevision()); 756a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.PutIsUnappliedUpdate(true); 757a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.PutServerParentId(TestIdFactory::MakeServer("Y")); 758a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 759a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 760a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Item 'Y' is child of 'X'. 761a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnsyncedItem( 762a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TestIdFactory::MakeServer("Y"), TestIdFactory::MakeServer("X"), "Y", true, 763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BOOKMARKS, NULL); 764a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 765a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If the server's update were applied, we would have X be a child of Y, and Y 766a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // as a child of X. That's a directory loop. The UpdateApplicator should 767a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // prevent the update from being applied and note that this is a hierarchy 768a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // conflict. 769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 770a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 771a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status); 772a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 773a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // This should count as a hierarchy conflict. 774cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counters = GetBookmarksUpdateCounters(); 775cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); 776a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 777a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 778a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 779a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); 780a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(e.good()); 781a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(e.GetIsUnappliedUpdate()); 782a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(e.GetIsUnsynced()); 783a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 784a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 785a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 786a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Test update application where the update has been orphaned by a local folder 787a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// deletion. The update application attempt should fail. 788a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, 789a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HierarchyConflictDeletedParent) { 790a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create a locally deleted parent item. 791a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 parent_handle; 792a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnsyncedItem( 793a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Id::CreateFromServerId("parent"), TestIdFactory::root(), 794a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "parent", true, BOOKMARKS, &parent_handle); 795a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 796a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); 797a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::MutableEntry entry(&trans, 798a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::GET_BY_HANDLE, 799a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parent_handle); 800a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.PutIsDel(true); 801a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 802a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 803a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create an incoming child from the server. 804a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 child_handle = entry_factory()->CreateUnappliedNewItemWithParent( 805a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "child", DefaultBookmarkSpecifics(), "parent"); 806a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 807a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The server's update may seem valid to some other client, but on this client 808a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // that new item's parent no longer exists. The update should not be applied 809a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // and the update applicator should indicate this is a hierarchy conflict. 810a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 811a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 812a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status); 813cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counters = GetBookmarksUpdateCounters(); 814cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); 815a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 816a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 817a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 818a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry child(&trans, syncable::GET_BY_HANDLE, child_handle); 819a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(child.good()); 820a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(child.GetIsUnappliedUpdate()); 821a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(child.GetIsUnsynced()); 822a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 823a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 824a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 825a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Attempt to apply an update that deletes a folder where the folder has 826a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// locally-created children. The update application should fail. 827a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, 828a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HierarchyConflictDeleteNonEmptyDirectory) { 829a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create a server-deleted folder as a child of root node. 830a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 parent_handle = 831a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateSyncedItem("parent", BOOKMARKS, true); 832a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 833a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); 834a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::MutableEntry entry(&trans, 835a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::GET_BY_HANDLE, 836a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parent_handle); 837a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(entry.good()); 838a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 839a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Delete it on the server. 840a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.PutServerVersion(entry_factory()->GetNextRevision()); 841a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.PutIsUnappliedUpdate(true); 842a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.PutServerParentId(TestIdFactory::root()); 843a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry.PutServerIsDel(true); 844a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 845a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 846a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create a local child of the server-deleted directory. 847a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnsyncedItem( 848a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TestIdFactory::MakeServer("child"), TestIdFactory::MakeServer("parent"), 849a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "child", false, BOOKMARKS, NULL); 850a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 851a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The server's request to delete the directory must be ignored, otherwise our 852a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // unsynced new child would be orphaned. This is a hierarchy conflict. 853a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 854a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 855a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status); 856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 857a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // This should count as a hierarchy conflict. 858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counters = GetBookmarksUpdateCounters(); 859cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); 860a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 861a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 862a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 863a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry parent(&trans, syncable::GET_BY_HANDLE, parent_handle); 864a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(parent.good()); 865a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(parent.GetIsUnappliedUpdate()); 866a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(parent.GetIsUnsynced()); 867a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 868a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 869a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 870a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Attempt to apply updates where the updated item's parent is not known to this 871a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// client. The update application attempt should fail. 872a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, 873a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HierarchyConflictUnknownParent) { 874a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We shouldn't be able to do anything with either of these items. 875a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 x_handle = entry_factory()->CreateUnappliedNewItemWithParent( 876a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "some_item", DefaultBookmarkSpecifics(), "unknown_parent"); 877a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 y_handle = entry_factory()->CreateUnappliedNewItemWithParent( 878a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "some_other_item", DefaultBookmarkSpecifics(), "some_item"); 879a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 880a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 881a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status); 882a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 883cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counters = GetBookmarksUpdateCounters(); 884cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(2, counters.num_hierarchy_conflict_application_failures) 885a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "All updates with an unknown ancestors should be in conflict"; 886cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0, counters.num_updates_applied) 887a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "No item with an unknown ancestor should be applied"; 888a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 889a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 890a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 891a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry x(&trans, syncable::GET_BY_HANDLE, x_handle); 892a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry y(&trans, syncable::GET_BY_HANDLE, y_handle); 893a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(x.good()); 894a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(y.good()); 895a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(x.GetIsUnappliedUpdate()); 896a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(y.GetIsUnappliedUpdate()); 897a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(x.GetIsUnsynced()); 898a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(y.GetIsUnsynced()); 899a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 900a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 901a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 902a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Attempt application of a mix of items. Some update application attempts will 903a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// fail due to hierarchy conflicts. Others should succeed. 904a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, ItemsBothKnownAndUnknown) { 905a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // See what happens when there's a mixture of good and bad updates. 906a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string root_server_id = syncable::GetNullId().GetServerId(); 907a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 u1_handle = entry_factory()->CreateUnappliedNewItemWithParent( 908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "first_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); 909a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 k1_handle = entry_factory()->CreateUnappliedNewItemWithParent( 910a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "first_known_item", DefaultBookmarkSpecifics(), root_server_id); 911a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 u2_handle = entry_factory()->CreateUnappliedNewItemWithParent( 912a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "second_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); 913a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 k2_handle = entry_factory()->CreateUnappliedNewItemWithParent( 914a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "second_known_item", DefaultBookmarkSpecifics(), "first_known_item"); 915a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 k3_handle = entry_factory()->CreateUnappliedNewItemWithParent( 916a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "third_known_item", DefaultBookmarkSpecifics(), "fourth_known_item"); 917a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 k4_handle = entry_factory()->CreateUnappliedNewItemWithParent( 918a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "fourth_known_item", DefaultBookmarkSpecifics(), root_server_id); 919a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 920a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 921a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status); 922a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 923cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counters = GetBookmarksUpdateCounters(); 924cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(2, counters.num_hierarchy_conflict_application_failures) 925a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "The updates with unknown ancestors should be in conflict"; 926cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(4, counters.num_updates_applied) 927a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "The updates with known ancestors should be successfully applied"; 928a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 929a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 930a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 931a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry u1(&trans, syncable::GET_BY_HANDLE, u1_handle); 932a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry u2(&trans, syncable::GET_BY_HANDLE, u2_handle); 933a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry k1(&trans, syncable::GET_BY_HANDLE, k1_handle); 934a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry k2(&trans, syncable::GET_BY_HANDLE, k2_handle); 935a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry k3(&trans, syncable::GET_BY_HANDLE, k3_handle); 936a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry k4(&trans, syncable::GET_BY_HANDLE, k4_handle); 937a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(u1.good()); 938a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(u2.good()); 939a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(k1.good()); 940a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(k2.good()); 941a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(k3.good()); 942a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(k4.good()); 943a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(u1.GetIsUnappliedUpdate()); 944a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(u2.GetIsUnappliedUpdate()); 945a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(k1.GetIsUnappliedUpdate()); 946a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(k2.GetIsUnappliedUpdate()); 947a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(k3.GetIsUnappliedUpdate()); 948a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(k4.GetIsUnappliedUpdate()); 949a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 950a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 951a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 952a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Attempt application of password upates where the passphrase is known. 953a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, DecryptablePassword) { 954a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Decryptable password updates should be applied. 955a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Cryptographer* cryptographer; 956a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 957a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Storing the cryptographer separately is bad, but for this test we 958a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // know it's safe. 959a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 960a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cryptographer = directory()->GetCryptographer(&trans); 961a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 962a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 963a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) KeyParams params = {"localhost", "dummy", "foobar"}; 964a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cryptographer->AddKey(params); 965a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 966a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::EntitySpecifics specifics; 967a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::PasswordSpecificsData data; 968a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) data.set_origin("http://example.com"); 969a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 970a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cryptographer->Encrypt(data, 971a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) specifics.mutable_password()->mutable_encrypted()); 972a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 handle = 973a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnappliedNewItem("item", specifics, false); 974a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 975a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 976a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyPasswordUpdates(&status); 977a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 978cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counters = GetPasswordsUpdateCounters(); 979cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1, counters.num_updates_applied) 980a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "The updates that can be decrypted should be applied"; 981a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 982a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 983a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 984a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); 985a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(e.good()); 986a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(e.GetIsUnappliedUpdate()); 987a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(e.GetIsUnsynced()); 988a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 989a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 990a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 991a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Attempt application of encrypted items when the passphrase is not known. 992a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, UndecryptableData) { 993a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Undecryptable updates should not be applied. 994a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::EntitySpecifics encrypted_bookmark; 995a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) encrypted_bookmark.mutable_encrypted(); 996a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddDefaultFieldValue(BOOKMARKS, &encrypted_bookmark); 997a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string root_server_id = syncable::GetNullId().GetServerId(); 998a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 folder_handle = entry_factory()->CreateUnappliedNewItemWithParent( 999a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "folder", 1000a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) encrypted_bookmark, 1001a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) root_server_id); 1002a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 bookmark_handle = entry_factory()->CreateUnappliedNewItem( 1003a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "item2", 1004a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) encrypted_bookmark, 1005a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) false); 1006a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::EntitySpecifics encrypted_password; 1007a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) encrypted_password.mutable_password(); 1008a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 password_handle = entry_factory()->CreateUnappliedNewItem( 1009a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "item3", 1010a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) encrypted_password, 1011a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) false); 1012a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1013a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 1014a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyBookmarkUpdates(&status); 1015a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyPasswordUpdates(&status); 1016a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1017cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& bm_counters = GetBookmarksUpdateCounters(); 1018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(2, bm_counters.num_encryption_conflict_application_failures) 1019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << "Updates that can't be decrypted should be in encryption conflict"; 1020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0, bm_counters.num_updates_applied) 1021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << "No update that can't be decrypted should be applied"; 1022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& pw_counters = GetPasswordsUpdateCounters(); 1024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1, pw_counters.num_encryption_conflict_application_failures) 1025a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "Updates that can't be decrypted should be in encryption conflict"; 1026cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(0, pw_counters.num_updates_applied) 1027a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "No update that can't be decrypted should be applied"; 1028a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1029a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 1030a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 1031a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry folder(&trans, syncable::GET_BY_HANDLE, folder_handle); 1032a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry bm(&trans, syncable::GET_BY_HANDLE, bookmark_handle); 1033a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry pw(&trans, syncable::GET_BY_HANDLE, password_handle); 1034a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(folder.good()); 1035a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(bm.good()); 1036a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(pw.good()); 1037a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(folder.GetIsUnappliedUpdate()); 1038a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(bm.GetIsUnappliedUpdate()); 1039a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(pw.GetIsUnappliedUpdate()); 1040a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1041a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1042a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1043a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Test a mix of decryptable and undecryptable updates. 1044a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SomeUndecryptablePassword) { 1045a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Cryptographer* cryptographer; 1046a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1047a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 decryptable_handle = -1; 1048a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 undecryptable_handle = -1; 1049a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1050a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Only decryptable password updates should be applied. 1051a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 1052a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::EntitySpecifics specifics; 1053a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::PasswordSpecificsData data; 1054a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) data.set_origin("http://example.com/1"); 1055a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 1056a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 1057a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cryptographer = directory()->GetCryptographer(&trans); 1058a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1059a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) KeyParams params = {"localhost", "dummy", "foobar"}; 1060a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cryptographer->AddKey(params); 1061a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1062a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cryptographer->Encrypt(data, 1063a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) specifics.mutable_password()->mutable_encrypted()); 1064a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1065a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) decryptable_handle = 1066a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnappliedNewItem("item1", specifics, false); 1067a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1068a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 1069a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create a new cryptographer, independent of the one in the session. 1070a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Cryptographer other_cryptographer(cryptographer->encryptor()); 1071a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) KeyParams params = {"localhost", "dummy", "bazqux"}; 1072a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) other_cryptographer.AddKey(params); 1073a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1074a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::EntitySpecifics specifics; 1075a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_pb::PasswordSpecificsData data; 1076a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) data.set_origin("http://example.com/2"); 1077a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1078a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) other_cryptographer.Encrypt(data, 1079a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) specifics.mutable_password()->mutable_encrypted()); 1080a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) undecryptable_handle = 1081a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) entry_factory()->CreateUnappliedNewItem("item2", specifics, false); 1082a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1083a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1084a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sessions::StatusController status; 1085a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ApplyPasswordUpdates(&status); 1086a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1087cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UpdateCounters& counters = GetPasswordsUpdateCounters(); 1088cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1, counters.num_encryption_conflict_application_failures) 1089a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "The updates that can't be decrypted should be in encryption " 1090a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "conflict"; 1091cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(1, counters.num_updates_applied) 1092a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "The undecryptable password update shouldn't be applied"; 1093a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1094a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 1095a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, directory()); 1096a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry e1(&trans, syncable::GET_BY_HANDLE, decryptable_handle); 1097a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) syncable::Entry e2(&trans, syncable::GET_BY_HANDLE, undecryptable_handle); 1098a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(e1.good()); 1099a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(e2.good()); 1100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(e1.GetIsUnappliedUpdate()); 1101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(e2.GetIsUnappliedUpdate()); 1102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1105116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(DirectoryUpdateHandlerApplyUpdateTest, 1106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SimpleConflictDifferentAttachmentMetadata) { 1107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const bool is_folder = false; 1108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::EntitySpecifics specifics; 1109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *specifics.mutable_article() = sync_pb::ArticleSpecifics(); 1110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int64 handle = entry_factory()->CreateSyncedItem("art1", ARTICLES, is_folder); 1111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentIdProto local_attachment_id = CreateAttachmentIdProto(); 1113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentIdProto server_attachment_id = CreateAttachmentIdProto(); 1114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Add an attachment to the local attachment metadata. 1116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentMetadata local_metadata; 1117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentMetadataRecord* local_record = local_metadata.add_record(); 1118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *local_record->mutable_id() = local_attachment_id; 1119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch local_record->set_is_on_server(true); 1120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch entry_factory()->SetLocalAttachmentMetadataForItem(handle, local_metadata); 1121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Add a different attachment to the server attachment metadata. 1123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentMetadata server_metadata; 1124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentMetadataRecord* server_record = 1125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch server_metadata.add_record(); 1126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *server_record->mutable_id() = server_attachment_id; 1127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch server_record->set_is_on_server(true); 1128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch entry_factory()->SetServerAttachmentMetadataForItem(handle, server_metadata); 1129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // At this point we have a simple conflict. The server says art1 should have 1131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // server_attachment_id, but the local sync engine says it should have 1132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // local_attachment_id. 1133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sessions::StatusController status; 1135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ApplyArticlesUpdates(&status); 1136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // See that the server won. 1138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const UpdateCounters& counters = GetArticlesUpdateCounters(); 1139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(1, counters.num_updates_applied); 1140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(1, counters.num_local_overwrites); 1141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(0, counters.num_server_overwrites); 1142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch local_metadata = entry_factory()->GetLocalAttachmentMetadataForItem(handle); 1143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(server_metadata.SerializeAsString(), 1144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch local_metadata.SerializeAsString()); 1145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 1146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1147116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(DirectoryUpdateHandlerApplyUpdateTest, 1148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SimpleConflictSameAttachmentMetadataDifferentOrder) { 1149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const bool is_folder = false; 1150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::EntitySpecifics specifics; 1151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *specifics.mutable_article() = sync_pb::ArticleSpecifics(); 1152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int64 handle = entry_factory()->CreateSyncedItem("art1", ARTICLES, is_folder); 1153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentIdProto id1 = CreateAttachmentIdProto(); 1155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentIdProto id2 = CreateAttachmentIdProto(); 1156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Add id1, then id2 to the local attachment metadata. 1158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentMetadata local_metadata; 1159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentMetadataRecord* record = local_metadata.add_record(); 1160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *record->mutable_id() = id1; 1161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch record->set_is_on_server(true); 1162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch record = local_metadata.add_record(); 1163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *record->mutable_id() = id2; 1164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch record->set_is_on_server(true); 1165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch entry_factory()->SetLocalAttachmentMetadataForItem(handle, local_metadata); 1166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Add id1 and id2 to the server attachment metadata, but in reverse order. 1168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::AttachmentMetadata server_metadata; 1169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch record = server_metadata.add_record(); 1170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *record->mutable_id() = id2; 1171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch record->set_is_on_server(true); 1172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch record = local_metadata.add_record(); 1173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *record->mutable_id() = id1; 1174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch record->set_is_on_server(true); 1175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch entry_factory()->SetServerAttachmentMetadataForItem(handle, server_metadata); 1176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // At this point we have a (false) conflict. 1178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sessions::StatusController status; 1180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ApplyArticlesUpdates(&status); 1181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // See that the server won. 1183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const UpdateCounters& counters = GetArticlesUpdateCounters(); 1184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(1, counters.num_updates_applied); 1185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(1, counters.num_local_overwrites); 1186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(0, counters.num_server_overwrites); 1187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch local_metadata = entry_factory()->GetLocalAttachmentMetadataForItem(handle); 1188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(server_metadata.SerializeAsString(), 1189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch local_metadata.SerializeAsString()); 1190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 1191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 11921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} // namespace syncer 1193