10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 20529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 30529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// found in the LICENSE file. 40529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "sync/syncable/directory_unittest.h" 60529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/stringprintf.h" 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/test/values_test_util.h" 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "sync/internal_api/public/base/attachment_id_proto.h" 100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "sync/syncable/syncable_proto_util.h" 110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "sync/syncable/syncable_util.h" 120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "sync/syncable/syncable_write_transaction.h" 130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "sync/test/engine/test_syncable_utils.h" 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "sync/test/test_directory_backing_store.h" 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing base::ExpectDictBooleanValue; 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing base::ExpectDictStringValue; 180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace syncer { 200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace syncable { 220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace { 240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool IsLegalNewParent(const Entry& a, const Entry& b) { 260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return IsLegalNewParent(a.trans(), a.GetId(), b.GetId()); 270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid PutDataAsBookmarkFavicon(WriteTransaction* wtrans, 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry* e, 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const char* bytes, 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t bytes_length) { 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sync_pb::EntitySpecifics specifics; 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu specifics.mutable_bookmark()->set_url("http://demo/"); 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu specifics.mutable_bookmark()->set_favicon(bytes, bytes_length); 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu e->PutSpecifics(specifics); 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid ExpectDataFromBookmarkFaviconEquals(BaseTransaction* trans, 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry* e, 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const char* bytes, 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t bytes_length) { 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(e->good()); 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(e->GetSpecifics().has_bookmark()); 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ("http://demo/", e->GetSpecifics().bookmark().url()); 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(std::string(bytes, bytes_length), 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu e->GetSpecifics().bookmark().favicon()); 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} // namespace 510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst char SyncableDirectoryTest::kDirectoryName[] = "Foo"; 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 540529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochSyncableDirectoryTest::SyncableDirectoryTest() { 550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 570529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochSyncableDirectoryTest::~SyncableDirectoryTest() { 580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SyncableDirectoryTest::SetUp() { 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(connection_.OpenInMemory()); 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ(OPENED, ReopenDirectory()); 630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SyncableDirectoryTest::TearDown() { 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (dir_) 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir_->SaveChanges(); 680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir_.reset(); 690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuDirOpenResult SyncableDirectoryTest::ReopenDirectory() { 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Use a TestDirectoryBackingStore and sql::Connection so we can have test 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // data persist across Directory object lifetimes while getting the 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // performance benefits of not writing to disk. 755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir_.reset( 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu new Directory(new TestDirectoryBackingStore(kDirectoryName, &connection_), 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu &handler_, 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu NULL, 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu NULL, 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu NULL)); 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DirOpenResult open_result = 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir_->Open(kDirectoryName, &delegate_, NullTransactionObserver()); 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (open_result != OPENED) { 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dir_.reset(); 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return open_result; 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Creates an empty entry and sets the ID field to a default one. 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void SyncableDirectoryTest::CreateEntry(const ModelType& model_type, 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& entryname) { 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateEntry(model_type, entryname, TestIdFactory::FromNumber(-99)); 960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Creates an empty entry and sets the ID field to id. 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void SyncableDirectoryTest::CreateEntry(const ModelType& model_type, 100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& entryname, 1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const int id) { 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateEntry(model_type, entryname, TestIdFactory::FromNumber(id)); 1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void SyncableDirectoryTest::CreateEntry(const ModelType& model_type, 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& entryname, 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Id& id) { 108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateEntryWithAttachmentMetadata( 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) model_type, entryname, id, sync_pb::AttachmentMetadata()); 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void SyncableDirectoryTest::CreateEntryWithAttachmentMetadata( 113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const ModelType& model_type, 114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& entryname, 115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Id& id, 116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const sync_pb::AttachmentMetadata& attachment_metadata) { 1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction wtrans(FROM_HERE, UNITTEST, dir_.get()); 118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MutableEntry me(&wtrans, CREATE, model_type, wtrans.root_id(), entryname); 1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(me.good()); 1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch me.PutId(id); 121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) me.PutAttachmentMetadata(attachment_metadata); 1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch me.PutIsUnsynced(true); 1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void SyncableDirectoryTest::DeleteEntry(const Id& id) { 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MutableEntry entry(&trans, GET_BY_ID, id); 128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_TRUE(entry.good()); 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) entry.PutIsDel(true); 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1320529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochDirOpenResult SyncableDirectoryTest::SimulateSaveAndReloadDir() { 1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!dir_->SaveChanges()) 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return FAILED_IN_UNITTEST; 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return ReopenDirectory(); 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1390529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochDirOpenResult SyncableDirectoryTest::SimulateCrashAndReloadDir() { 1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return ReopenDirectory(); 1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SyncableDirectoryTest::GetAllMetaHandles(BaseTransaction* trans, 1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MetahandleSet* result) { 1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir_->GetAllMetaHandles(trans, result); 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SyncableDirectoryTest::CheckPurgeEntriesWithTypeInSucceeded( 1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ModelTypeSet types_to_purge, 1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool before_reload) { 1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SCOPED_TRACE(testing::Message("Before reload: ") << before_reload); 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadTransaction trans(FROM_HERE, dir_.get()); 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MetahandleSet all_set; 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir_->GetAllMetaHandles(&trans, &all_set); 1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(4U, all_set.size()); 1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (before_reload) 1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(6U, dir_->kernel_->metahandles_to_purge.size()); 1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (MetahandleSet::iterator iter = all_set.begin(); iter != all_set.end(); 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++iter) { 1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry e(&trans, GET_BY_HANDLE, *iter); 1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ModelType local_type = e.GetModelType(); 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ModelType server_type = e.GetServerModelType(); 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Note the dance around incrementing |it|, since we sometimes erase(). 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if ((IsRealDataType(local_type) && types_to_purge.Has(local_type)) || 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (IsRealDataType(server_type) && types_to_purge.Has(server_type))) { 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FAIL() << "Illegal type should have been deleted."; 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (ModelTypeSet::Iterator it = types_to_purge.First(); it.Good(); 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it.Inc()) { 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_FALSE(dir_->InitialSyncEndedForType(it.Get())); 1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sync_pb::DataTypeProgressMarker progress; 1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir_->GetDownloadProgress(it.Get(), &progress); 1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ("", progress.token()); 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadTransaction trans(FROM_HERE, dir_.get()); 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sync_pb::DataTypeContext context; 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir_->GetDataTypeContext(&trans, it.Get(), &context); 1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(context.SerializeAsString().empty()); 1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_FALSE(types_to_purge.Has(BOOKMARKS)); 1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(dir_->InitialSyncEndedForType(BOOKMARKS)); 1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool SyncableDirectoryTest::IsInDirtyMetahandles(int64 metahandle) { 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return 1 == dir_->kernel_->dirty_metahandles.count(metahandle); 1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool SyncableDirectoryTest::IsInMetahandlesToPurge(int64 metahandle) { 1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return 1 == dir_->kernel_->metahandles_to_purge.count(metahandle); 1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochscoped_ptr<Directory>& SyncableDirectoryTest::dir() { 1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return dir_; 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2010529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochDirectoryChangeDelegate* SyncableDirectoryTest::directory_change_delegate() { 2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return &delegate_; 2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2050529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochEncryptor* SyncableDirectoryTest::encryptor() { 2060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return &encryptor_; 2070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2090529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochUnrecoverableErrorHandler* 2100529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochSyncableDirectoryTest::unrecoverable_error_handler() { 2110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return &handler_; 2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SyncableDirectoryTest::ValidateEntry(BaseTransaction* trans, 2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 id, 2160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool check_name, 2170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string& name, 2180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 base_version, 2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 server_version, 2200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool is_del) { 2210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry e(trans, GET_BY_ID, TestIdFactory::FromNumber(id)); 2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e.good()); 2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (check_name) 2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(name == e.GetNonUniqueName()); 2250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(base_version == e.GetBaseVersion()); 2260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(server_version == e.GetServerVersion()); 2270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(is_del == e.GetIsDel()); 2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2300529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TakeSnapshotGetsMetahandlesToPurge) { 2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const int metas_to_create = 50; 2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MetahandleSet expected_purges; 2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MetahandleSet all_handles; 2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dir()->SetDownloadProgress(BOOKMARKS, BuildProgress(BOOKMARKS)); 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dir()->SetDownloadProgress(PREFERENCES, BuildProgress(PREFERENCES)); 2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (int i = 0; i < metas_to_create; i++) { 2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e(&trans, CREATE, BOOKMARKS, trans.root_id(), "foo"); 2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e.PutIsUnsynced(true); 2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sync_pb::EntitySpecifics specs; 2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (i % 2 == 0) { 2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch AddDefaultFieldValue(BOOKMARKS, &specs); 2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch expected_purges.insert(e.GetMetahandle()); 2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch all_handles.insert(e.GetMetahandle()); 2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch AddDefaultFieldValue(PREFERENCES, &specs); 2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch all_handles.insert(e.GetMetahandle()); 2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e.PutSpecifics(specs); 2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e.PutServerSpecifics(specs); 2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ModelTypeSet to_purge(BOOKMARKS); 2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->PurgeEntriesWithTypeIn(to_purge, ModelTypeSet(), ModelTypeSet()); 2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Directory::SaveChangesSnapshot snapshot1; 2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock scoped_lock(dir()->kernel_->save_changes_mutex); 2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->TakeSnapshotForSaveChanges(&snapshot1); 2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(expected_purges == snapshot1.metahandles_to_purge); 2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_purge.Clear(); 2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_purge.Put(PREFERENCES); 2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->PurgeEntriesWithTypeIn(to_purge, ModelTypeSet(), ModelTypeSet()); 2660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->HandleSaveChangesFailure(snapshot1); 2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Directory::SaveChangesSnapshot snapshot2; 2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->TakeSnapshotForSaveChanges(&snapshot2); 2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(all_handles == snapshot2.metahandles_to_purge); 2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2740529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TakeSnapshotGetsAllDirtyHandlesTest) { 2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const int metahandles_to_create = 100; 2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<int64> expected_dirty_metahandles; 2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (int i = 0; i < metahandles_to_create; i++) { 2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e(&trans, CREATE, BOOKMARKS, trans.root_id(), "foo"); 2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch expected_dirty_metahandles.push_back(e.GetMetahandle()); 2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e.PutIsUnsynced(true); 2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Fake SaveChanges() and make sure we got what we expected. 2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Directory::SaveChangesSnapshot snapshot; 2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock scoped_lock(dir()->kernel_->save_changes_mutex); 2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->TakeSnapshotForSaveChanges(&snapshot); 2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Make sure there's an entry for each new metahandle. Make sure all 2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // entries are marked dirty. 2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(expected_dirty_metahandles.size(), snapshot.dirty_metas.size()); 2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); 2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != snapshot.dirty_metas.end(); 2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i) { 2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE((*i)->is_dirty()); 2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->VacuumAfterSaveChanges(snapshot); 2990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Put a new value with existing transactions as well as adding new ones. 3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<int64> new_dirty_metahandles; 3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::vector<int64>::const_iterator i = 3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch expected_dirty_metahandles.begin(); 3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != expected_dirty_metahandles.end(); 3070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i) { 3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Change existing entries to directories to dirty them. 3090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e1(&trans, GET_BY_HANDLE, *i); 3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsDir(true); 3110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsUnsynced(true); 3120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Add new entries 3130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e2(&trans, CREATE, BOOKMARKS, trans.root_id(), "bar"); 3140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutIsUnsynced(true); 3150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new_dirty_metahandles.push_back(e2.GetMetahandle()); 3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch expected_dirty_metahandles.insert(expected_dirty_metahandles.end(), 3180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new_dirty_metahandles.begin(), 3190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new_dirty_metahandles.end()); 3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Fake SaveChanges() and make sure we got what we expected. 3220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 3230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Directory::SaveChangesSnapshot snapshot; 3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock scoped_lock(dir()->kernel_->save_changes_mutex); 3250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->TakeSnapshotForSaveChanges(&snapshot); 3260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Make sure there's an entry for each new metahandle. Make sure all 3270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // entries are marked dirty. 3280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(expected_dirty_metahandles.size(), snapshot.dirty_metas.size()); 3290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); 3300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != snapshot.dirty_metas.end(); 3310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i) { 3320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE((*i)->is_dirty()); 3330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->VacuumAfterSaveChanges(snapshot); 3350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3380529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TakeSnapshotGetsOnlyDirtyHandlesTest) { 3390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const int metahandles_to_create = 100; 3400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // half of 2 * metahandles_to_create 3420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const unsigned int number_changed = 100u; 3430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<int64> expected_dirty_metahandles; 3440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 3450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 3460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (int i = 0; i < metahandles_to_create; i++) { 3470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e(&trans, CREATE, BOOKMARKS, trans.root_id(), "foo"); 3480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch expected_dirty_metahandles.push_back(e.GetMetahandle()); 3490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e.PutIsUnsynced(true); 3500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 3530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Put a new value with existing transactions as well as adding new ones. 3540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 3550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<int64> new_dirty_metahandles; 3570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::vector<int64>::const_iterator i = 3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch expected_dirty_metahandles.begin(); 3590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != expected_dirty_metahandles.end(); 3600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i) { 3610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Change existing entries to directories to dirty them. 3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e1(&trans, GET_BY_HANDLE, *i); 3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e1.good()); 3640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsDir(true); 3650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsUnsynced(true); 3660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Add new entries 3670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e2(&trans, CREATE, BOOKMARKS, trans.root_id(), "bar"); 3680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutIsUnsynced(true); 3690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new_dirty_metahandles.push_back(e2.GetMetahandle()); 3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch expected_dirty_metahandles.insert(expected_dirty_metahandles.end(), 3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new_dirty_metahandles.begin(), 3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new_dirty_metahandles.end()); 3740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 3760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Don't make any changes whatsoever and ensure nothing comes back. 3770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 3790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::vector<int64>::const_iterator i = 3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch expected_dirty_metahandles.begin(); 3810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != expected_dirty_metahandles.end(); 3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i) { 3830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e(&trans, GET_BY_HANDLE, *i); 3840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e.good()); 3850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // We aren't doing anything to dirty these entries. 3860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Fake SaveChanges() and make sure we got what we expected. 3890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 3900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Directory::SaveChangesSnapshot snapshot; 3910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock scoped_lock(dir()->kernel_->save_changes_mutex); 3920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->TakeSnapshotForSaveChanges(&snapshot); 3930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Make sure there are no dirty_metahandles. 3940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(0u, snapshot.dirty_metas.size()); 3950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->VacuumAfterSaveChanges(snapshot); 3960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 3980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 3990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool should_change = false; 4000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::vector<int64>::const_iterator i = 4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch expected_dirty_metahandles.begin(); 4020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != expected_dirty_metahandles.end(); 4030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i) { 4040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Maybe change entries by flipping IS_DIR. 4050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e(&trans, GET_BY_HANDLE, *i); 4060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e.good()); 4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch should_change = !should_change; 4080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (should_change) { 4090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool not_dir = !e.GetIsDir(); 4100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e.PutIsDir(not_dir); 4110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e.PutIsUnsynced(true); 4120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Fake SaveChanges() and make sure we got what we expected. 4160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 4170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Directory::SaveChangesSnapshot snapshot; 4180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock scoped_lock(dir()->kernel_->save_changes_mutex); 4190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->TakeSnapshotForSaveChanges(&snapshot); 4200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Make sure there's an entry for each changed metahandle. Make sure all 4210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // entries are marked dirty. 4220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(number_changed, snapshot.dirty_metas.size()); 4230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); 4240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != snapshot.dirty_metas.end(); 4250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i) { 4260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE((*i)->is_dirty()); 4270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->VacuumAfterSaveChanges(snapshot); 4290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Test delete journals management. 4330529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, ManageDeleteJournals) { 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sync_pb::EntitySpecifics bookmark_specifics; 4350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch AddDefaultFieldValue(BOOKMARKS, &bookmark_specifics); 4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bookmark_specifics.mutable_bookmark()->set_url("url"); 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id id1 = TestIdFactory::FromNumber(-1); 4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id id2 = TestIdFactory::FromNumber(-2); 4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 handle1 = 0; 4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 handle2 = 0; 4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 4430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create two bookmark entries and save in database. 444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateEntry(BOOKMARKS, "item1", id1); 445010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateEntry(BOOKMARKS, "item2", id2); 4460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 4470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 4480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry item1(&trans, GET_BY_ID, id1); 4490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(item1.good()); 4500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle1 = item1.GetMetahandle(); 4510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item1.PutSpecifics(bookmark_specifics); 4520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item1.PutServerSpecifics(bookmark_specifics); 4530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry item2(&trans, GET_BY_ID, id2); 4540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(item2.good()); 4550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle2 = item2.GetMetahandle(); 4560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item2.PutSpecifics(bookmark_specifics); 4570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item2.PutServerSpecifics(bookmark_specifics); 4580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(OPENED, SimulateSaveAndReloadDir()); 4600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { // Test adding and saving delete journals. 4630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DeleteJournal* delete_journal = dir()->delete_journal(); 4640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 4650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 4660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EntryKernelSet journal_entries; 4670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch delete_journal->GetDeleteJournals(&trans, BOOKMARKS, &journal_entries); 4680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(0u, journal_entries.size()); 4690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Set SERVER_IS_DEL of the entries to true and they should be added to 4710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // delete journals. 4720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry item1(&trans, GET_BY_ID, id1); 4730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(item1.good()); 4740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item1.PutServerIsDel(true); 4750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry item2(&trans, GET_BY_ID, id2); 4760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(item2.good()); 4770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item2.PutServerIsDel(true); 4780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EntryKernel tmp; 4790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch tmp.put(ID, id1); 4800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(delete_journal->delete_journals_.count(&tmp)); 4810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch tmp.put(ID, id2); 4820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(delete_journal->delete_journals_.count(&tmp)); 4830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Save delete journals in database and verify memory clearing. 4860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(dir()->SaveChanges()); 4870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 4880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadTransaction trans(FROM_HERE, dir().get()); 4890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(0u, delete_journal->GetDeleteJournalSize(&trans)); 4900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(OPENED, SimulateSaveAndReloadDir()); 4920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 4950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 4960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Test reading delete journals from database. 4970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 4980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DeleteJournal* delete_journal = dir()->delete_journal(); 4990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EntryKernelSet journal_entries; 5000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch delete_journal->GetDeleteJournals(&trans, BOOKMARKS, &journal_entries); 5010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(2u, journal_entries.size()); 5020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EntryKernel tmp; 5030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch tmp.put(META_HANDLE, handle1); 5040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(journal_entries.count(&tmp)); 5050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch tmp.put(META_HANDLE, handle2); 5060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(journal_entries.count(&tmp)); 5070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Purge item2. 5090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MetahandleSet to_purge; 5100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_purge.insert(handle2); 5110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch delete_journal->PurgeDeleteJournals(&trans, to_purge); 5120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Verify that item2 is purged from journals in memory and will be 5140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // purged from database. 5150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch tmp.put(ID, id2); 5160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_FALSE(delete_journal->delete_journals_.count(&tmp)); 5170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(1u, delete_journal->delete_journals_to_purge_.size()); 5180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(delete_journal->delete_journals_to_purge_.count(handle2)); 5190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 5200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(OPENED, SimulateSaveAndReloadDir()); 5210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 5220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 5240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 5250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Verify purged entry is gone in database. 5260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 5270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DeleteJournal* delete_journal = dir()->delete_journal(); 5280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EntryKernelSet journal_entries; 5290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch delete_journal->GetDeleteJournals(&trans, BOOKMARKS, &journal_entries); 5300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(1u, journal_entries.size()); 5310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EntryKernel tmp; 5320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch tmp.put(ID, id1); 5330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch tmp.put(META_HANDLE, handle1); 5340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(journal_entries.count(&tmp)); 5350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Undelete item1. 5370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry item1(&trans, GET_BY_ID, id1); 5380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(item1.good()); 5390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item1.PutServerIsDel(false); 5400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(delete_journal->delete_journals_.empty()); 5410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(1u, delete_journal->delete_journals_to_purge_.size()); 5420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(delete_journal->delete_journals_to_purge_.count(handle1)); 5430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 5440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(OPENED, SimulateSaveAndReloadDir()); 5450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 5460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 5480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Verify undeleted entry is gone from database. 5490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadTransaction trans(FROM_HERE, dir().get()); 5500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DeleteJournal* delete_journal = dir()->delete_journal(); 5510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(0u, delete_journal->GetDeleteJournalSize(&trans)); 5520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 5530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 5540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5550529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestBasicLookupNonExistantID) { 5560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadTransaction rtrans(FROM_HERE, dir().get()); 5570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry e(&rtrans, GET_BY_ID, TestIdFactory::FromNumber(-99)); 5580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_FALSE(e.good()); 5590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 5600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5610529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestBasicLookupValidID) { 562010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateEntry(BOOKMARKS, "rtc"); 5630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadTransaction rtrans(FROM_HERE, dir().get()); 5640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry e(&rtrans, GET_BY_ID, TestIdFactory::FromNumber(-99)); 5650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e.good()); 5660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 5670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5680529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestDelete) { 5690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string name = "peanut butter jelly time"; 5700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 5710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e1(&trans, CREATE, BOOKMARKS, trans.root_id(), name); 5720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e1.good()); 5730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsDel(true); 5740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e2(&trans, CREATE, BOOKMARKS, trans.root_id(), name); 5750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e2.good()); 5760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutIsDel(true); 5770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e3(&trans, CREATE, BOOKMARKS, trans.root_id(), name); 5780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e3.good()); 5790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e3.PutIsDel(true); 5800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsDel(false); 5820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutIsDel(false); 5830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e3.PutIsDel(false); 5840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsDel(true); 5860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutIsDel(true); 5870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e3.PutIsDel(true); 5880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 5890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5900529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestGetUnsynced) { 5910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Directory::Metahandles handles; 5920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 handle1, handle2; 5930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 5940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 5950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnsyncedMetaHandles(&trans, &handles); 5970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(0 == handles.size()); 5980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e1(&trans, CREATE, BOOKMARKS, trans.root_id(), "abba"); 6000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e1.good()); 6010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle1 = e1.GetMetahandle(); 6020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutBaseVersion(1); 6030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsDir(true); 6040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutId(TestIdFactory::FromNumber(101)); 6050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e2(&trans, CREATE, BOOKMARKS, e1.GetId(), "bread"); 6070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e2.good()); 6080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle2 = e2.GetMetahandle(); 6090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutBaseVersion(1); 6100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutId(TestIdFactory::FromNumber(102)); 6110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 6130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 6140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 6150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnsyncedMetaHandles(&trans, &handles); 6170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(0 == handles.size()); 6180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e3(&trans, GET_BY_HANDLE, handle1); 6200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e3.good()); 6210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e3.PutIsUnsynced(true); 6220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 6240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 6250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 6260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnsyncedMetaHandles(&trans, &handles); 6270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(1 == handles.size()); 6280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle1 == handles[0]); 6290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e4(&trans, GET_BY_HANDLE, handle2); 6310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e4.good()); 6320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e4.PutIsUnsynced(true); 6330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 6350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 6360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 6370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnsyncedMetaHandles(&trans, &handles); 6380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(2 == handles.size()); 6390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (handle1 == handles[0]) { 6400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle2 == handles[1]); 6410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 6420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle2 == handles[0]); 6430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle1 == handles[1]); 6440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e5(&trans, GET_BY_HANDLE, handle1); 6470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e5.good()); 6480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e5.GetIsUnsynced()); 6490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e5.PutIsUnsynced(false)); 6500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_FALSE(e5.GetIsUnsynced()); 6510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 6530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 6540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 6550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnsyncedMetaHandles(&trans, &handles); 6560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(1 == handles.size()); 6570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle2 == handles[0]); 6580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 6600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6610529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestGetUnappliedUpdates) { 6620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<int64> handles; 6630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 handle1, handle2; 6640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const FullModelTypeSet all_types = FullModelTypeSet::All(); 6650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 6660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 6670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles); 6690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(0 == handles.size()); 6700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e1(&trans, CREATE, BOOKMARKS, trans.root_id(), "abba"); 6720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e1.good()); 6730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle1 = e1.GetMetahandle(); 6740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsUnappliedUpdate(false); 6750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutBaseVersion(1); 6760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutId(TestIdFactory::FromNumber(101)); 6770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e1.PutIsDir(true); 6780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e2(&trans, CREATE, BOOKMARKS, e1.GetId(), "bread"); 6800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e2.good()); 6810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle2 = e2.GetMetahandle(); 6820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutIsUnappliedUpdate(false); 6830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutBaseVersion(1); 6840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e2.PutId(TestIdFactory::FromNumber(102)); 6850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 6870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 6880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 6890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles); 6910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(0 == handles.size()); 6920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e3(&trans, GET_BY_HANDLE, handle1); 6940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e3.good()); 6950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e3.PutIsUnappliedUpdate(true); 6960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 6980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 6990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 7000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles); 7010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(1 == handles.size()); 7020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle1 == handles[0]); 7030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e4(&trans, GET_BY_HANDLE, handle2); 7050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e4.good()); 7060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e4.PutIsUnappliedUpdate(true); 7070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 7090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 7100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 7110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles); 7120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(2 == handles.size()); 7130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (handle1 == handles[0]) { 7140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle2 == handles[1]); 7150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 7160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle2 == handles[0]); 7170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle1 == handles[1]); 7180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry e5(&trans, GET_BY_HANDLE, handle1); 7210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(e5.good()); 7220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e5.PutIsUnappliedUpdate(false); 7230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 7250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 7260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 7270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles); 7280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(1 == handles.size()); 7290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(handle2 == handles[0]); 7300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 7320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7330529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, DeleteBug_531383) { 7340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Try to evoke a check failure... 7350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch TestIdFactory id_factory; 7360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 grandchild_handle; 7370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 7380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction wtrans(FROM_HERE, UNITTEST, dir().get()); 7390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent(&wtrans, CREATE, BOOKMARKS, id_factory.root(), "Bob"); 7400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(parent.good()); 7410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsDir(true); 7420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutId(id_factory.NewServerId()); 7430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutBaseVersion(1); 7440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry child(&wtrans, CREATE, BOOKMARKS, parent.GetId(), "Bob"); 7450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(child.good()); 7460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutIsDir(true); 7470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutId(id_factory.NewServerId()); 7480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutBaseVersion(1); 7490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry grandchild(&wtrans, CREATE, BOOKMARKS, child.GetId(), "Bob"); 7500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(grandchild.good()); 7510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild.PutId(id_factory.NewServerId()); 7520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild.PutBaseVersion(1); 7530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild.PutIsDel(true); 7540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry twin(&wtrans, CREATE, BOOKMARKS, child.GetId(), "Bob"); 7550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(twin.good()); 7560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch twin.PutIsDel(true); 7570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild.PutIsDel(false); 7580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild_handle = grandchild.GetMetahandle(); 7600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 7620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 7630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction wtrans(FROM_HERE, UNITTEST, dir().get()); 7640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry grandchild(&wtrans, GET_BY_HANDLE, grandchild_handle); 7650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild.PutIsDel(true); // Used to CHECK fail here. 7660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 7680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7690529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestIsLegalNewParent) { 7700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch TestIdFactory id_factory; 7710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction wtrans(FROM_HERE, UNITTEST, dir().get()); 7720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry root(&wtrans, GET_BY_ID, id_factory.root()); 7730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(root.good()); 7740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent(&wtrans, CREATE, BOOKMARKS, root.GetId(), "Bob"); 7750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(parent.good()); 7760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsDir(true); 7770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutId(id_factory.NewServerId()); 7780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutBaseVersion(1); 7790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry child(&wtrans, CREATE, BOOKMARKS, parent.GetId(), "Bob"); 7800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(child.good()); 7810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutIsDir(true); 7820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutId(id_factory.NewServerId()); 7830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutBaseVersion(1); 7840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry grandchild(&wtrans, CREATE, BOOKMARKS, child.GetId(), "Bob"); 7850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(grandchild.good()); 7860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild.PutId(id_factory.NewServerId()); 7870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild.PutBaseVersion(1); 7880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent2(&wtrans, CREATE, BOOKMARKS, root.GetId(), "Pete"); 7900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(parent2.good()); 7910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent2.PutIsDir(true); 7920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent2.PutId(id_factory.NewServerId()); 7930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent2.PutBaseVersion(1); 7940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry child2(&wtrans, CREATE, BOOKMARKS, parent2.GetId(), "Pete"); 7950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(child2.good()); 7960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child2.PutIsDir(true); 7970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child2.PutId(id_factory.NewServerId()); 7980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child2.PutBaseVersion(1); 7990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry grandchild2(&wtrans, CREATE, BOOKMARKS, child2.GetId(), "Pete"); 8000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(grandchild2.good()); 8010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild2.PutId(id_factory.NewServerId()); 8020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch grandchild2.PutBaseVersion(1); 8030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // resulting tree 8040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // root 8050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // / | 8060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // parent parent2 8070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // | | 8080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // child child2 8090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // | | 8100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // grandchild grandchild2 8110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(IsLegalNewParent(child, root)); 8120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(IsLegalNewParent(child, parent)); 8130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_FALSE(IsLegalNewParent(child, child)); 8140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_FALSE(IsLegalNewParent(child, grandchild)); 8150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(IsLegalNewParent(child, parent2)); 8160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(IsLegalNewParent(child, grandchild2)); 8170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_FALSE(IsLegalNewParent(parent, grandchild)); 8180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_FALSE(IsLegalNewParent(root, grandchild)); 8190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_FALSE(IsLegalNewParent(parent, grandchild)); 8200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 8210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8220529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestEntryIsInFolder) { 8230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create a subdir and an entry. 8240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 entry_handle; 8250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch syncable::Id folder_id; 8260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch syncable::Id entry_id; 8270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string entry_name = "entry"; 8280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 8300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 8310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry folder(&trans, CREATE, BOOKMARKS, trans.root_id(), "folder"); 8320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(folder.good()); 8330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutIsDir(true); 8340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(folder.PutIsUnsynced(true)); 8350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder_id = folder.GetId(); 8360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry entry(&trans, CREATE, BOOKMARKS, folder.GetId(), entry_name); 8380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(entry.good()); 8390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch entry_handle = entry.GetMetahandle(); 8400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch entry.PutIsUnsynced(true); 8410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch entry_id = entry.GetId(); 8420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 8430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Make sure we can find the entry in the folder. 8450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 8460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadTransaction trans(FROM_HERE, dir().get()); 8470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(0, CountEntriesWithName(&trans, trans.root_id(), entry_name)); 8480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(1, CountEntriesWithName(&trans, folder_id, entry_name)); 8490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry entry(&trans, GET_BY_ID, entry_id); 8510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(entry.good()); 8520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(entry_handle, entry.GetMetahandle()); 8530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(entry.GetNonUniqueName() == entry_name); 8540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(entry.GetParentId() == folder_id); 8550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 8560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 8570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8580529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestParentIdIndexUpdate) { 8590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string child_name = "child"; 8600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction wt(FROM_HERE, UNITTEST, dir().get()); 8620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent_folder(&wt, CREATE, BOOKMARKS, wt.root_id(), "folder1"); 8630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent_folder.PutIsUnsynced(true); 8640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent_folder.PutIsDir(true); 8650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent_folder2(&wt, CREATE, BOOKMARKS, wt.root_id(), "folder2"); 8670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent_folder2.PutIsUnsynced(true); 8680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent_folder2.PutIsDir(true); 8690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry child(&wt, CREATE, BOOKMARKS, parent_folder.GetId(), child_name); 8710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutIsDir(true); 8720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutIsUnsynced(true); 8730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(child.good()); 8750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(0, CountEntriesWithName(&wt, wt.root_id(), child_name)); 8770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(parent_folder.GetId(), child.GetParentId()); 8780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(1, CountEntriesWithName(&wt, parent_folder.GetId(), child_name)); 8790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(0, CountEntriesWithName(&wt, parent_folder2.GetId(), child_name)); 8800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutParentId(parent_folder2.GetId()); 8810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(parent_folder2.GetId(), child.GetParentId()); 8820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(0, CountEntriesWithName(&wt, parent_folder.GetId(), child_name)); 8830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(1, CountEntriesWithName(&wt, parent_folder2.GetId(), child_name)); 8840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 8850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8860529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestNoReindexDeletedItems) { 8870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string folder_name = "folder"; 8880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string new_name = "new_name"; 8890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 8910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry folder(&trans, CREATE, BOOKMARKS, trans.root_id(), folder_name); 8920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(folder.good()); 8930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutIsDir(true); 8940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutIsDel(true); 8950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(0, CountEntriesWithName(&trans, trans.root_id(), folder_name)); 8970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry deleted(&trans, GET_BY_ID, folder.GetId()); 8990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(deleted.good()); 9000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch deleted.PutParentId(trans.root_id()); 9010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch deleted.PutNonUniqueName(new_name); 9020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(0, CountEntriesWithName(&trans, trans.root_id(), folder_name)); 9040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(0, CountEntriesWithName(&trans, trans.root_id(), new_name)); 9050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 9060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9070529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, TestCaseChangeRename) { 9080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 9090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry folder(&trans, CREATE, BOOKMARKS, trans.root_id(), "CaseChange"); 9100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(folder.good()); 9110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutParentId(trans.root_id()); 9120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutNonUniqueName("CASECHANGE"); 9130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutIsDel(true); 9140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 9150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Create items of each model type, and check that GetModelType and 9170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// GetServerModelType return the right value. 9180529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, GetModelType) { 9190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch TestIdFactory id_factory; 9200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ModelTypeSet protocol_types = ProtocolTypes(); 9210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); 9220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch iter.Inc()) { 9230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ModelType datatype = iter.Get(); 9240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SCOPED_TRACE(testing::Message("Testing model type ") << datatype); 9250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch switch (datatype) { 9260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case UNSPECIFIED: 9270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case TOP_LEVEL_FOLDER: 9280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch continue; // Datatype isn't a function of Specifics. 9290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch default: 9300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 9310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 9320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sync_pb::EntitySpecifics specifics; 9330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch AddDefaultFieldValue(datatype, &specifics); 9340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 9360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry folder(&trans, CREATE, BOOKMARKS, trans.root_id(), "Folder"); 9380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(folder.good()); 9390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutId(id_factory.NewServerId()); 9400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutSpecifics(specifics); 9410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutBaseVersion(1); 9420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutIsDir(true); 9430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder.PutIsDel(false); 9440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(datatype, folder.GetModelType()); 9450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry item(&trans, CREATE, BOOKMARKS, trans.root_id(), "Item"); 9470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(item.good()); 9480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item.PutId(id_factory.NewServerId()); 9490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item.PutSpecifics(specifics); 9500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item.PutBaseVersion(1); 9510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item.PutIsDir(false); 9520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item.PutIsDel(false); 9530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(datatype, item.GetModelType()); 9540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // It's critical that deletion records retain their datatype, so that 9560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // they can be dispatched to the appropriate change processor. 9570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry deleted_item( 9580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &trans, CREATE, BOOKMARKS, trans.root_id(), "Deleted Item"); 9590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(item.good()); 9600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch deleted_item.PutId(id_factory.NewServerId()); 9610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch deleted_item.PutSpecifics(specifics); 9620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch deleted_item.PutBaseVersion(1); 9630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch deleted_item.PutIsDir(false); 9640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch deleted_item.PutIsDel(true); 9650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(datatype, deleted_item.GetModelType()); 9660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry server_folder( 9680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &trans, CREATE_NEW_UPDATE_ITEM, id_factory.NewServerId()); 9690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(server_folder.good()); 9700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_folder.PutServerSpecifics(specifics); 9710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_folder.PutBaseVersion(1); 9720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_folder.PutServerIsDir(true); 9730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_folder.PutServerIsDel(false); 9740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(datatype, server_folder.GetServerModelType()); 9750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry server_item( 9770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &trans, CREATE_NEW_UPDATE_ITEM, id_factory.NewServerId()); 9780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(server_item.good()); 9790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_item.PutServerSpecifics(specifics); 9800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_item.PutBaseVersion(1); 9810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_item.PutServerIsDir(false); 9820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_item.PutServerIsDel(false); 9830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(datatype, server_item.GetServerModelType()); 9840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sync_pb::SyncEntity folder_entity; 9860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder_entity.set_id_string(SyncableIdToProto(id_factory.NewServerId())); 9870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder_entity.set_deleted(false); 9880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder_entity.set_folder(true); 9890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch folder_entity.mutable_specifics()->CopyFrom(specifics); 9900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(datatype, GetModelType(folder_entity)); 9910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 9920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sync_pb::SyncEntity item_entity; 9930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item_entity.set_id_string(SyncableIdToProto(id_factory.NewServerId())); 9940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item_entity.set_deleted(false); 9950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item_entity.set_folder(false); 9960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch item_entity.mutable_specifics()->CopyFrom(specifics); 9970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(datatype, GetModelType(item_entity)); 9980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 9990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 10000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// A test that roughly mimics the directory interaction that occurs when a 10020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// bookmark folder and entry are created then synced for the first time. It is 10030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// a more common variant of the 'DeletedAndUnsyncedChild' scenario tested below. 10040529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, ChangeEntryIDAndUpdateChildren_ParentAndChild) { 10050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch TestIdFactory id_factory; 10060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id orig_parent_id; 10070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id orig_child_id; 10080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 10100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create two client-side items, a parent and child. 10110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 10120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent(&trans, CREATE, BOOKMARKS, id_factory.root(), "parent"); 10140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsDir(true); 10150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsUnsynced(true); 10160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry child(&trans, CREATE, BOOKMARKS, parent.GetId(), "child"); 10180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutIsUnsynced(true); 10190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch orig_parent_id = parent.GetId(); 10210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch orig_child_id = child.GetId(); 10220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 10230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 10250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Simulate what happens after committing two items. Their IDs will be 10260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // replaced with server IDs. The child is renamed first, then the parent. 10270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 10280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent(&trans, GET_BY_ID, orig_parent_id); 10300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry child(&trans, GET_BY_ID, orig_child_id); 10310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ChangeEntryIDAndUpdateChildren(&trans, &child, id_factory.NewServerId()); 10330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutIsUnsynced(false); 10340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutBaseVersion(1); 10350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutServerVersion(1); 10360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ChangeEntryIDAndUpdateChildren(&trans, &parent, id_factory.NewServerId()); 10380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsUnsynced(false); 10390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutBaseVersion(1); 10400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutServerVersion(1); 10410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 10420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Final check for validity. 10440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(OPENED, SimulateSaveAndReloadDir()); 10450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 10460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// A test based on the scenario where we create a bookmark folder and entry 10480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// locally, but with a twist. In this case, the bookmark is deleted before we 10490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// are able to sync either it or its parent folder. This scenario used to cause 10500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// directory corruption, see crbug.com/125381. 10510529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, 10520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ChangeEntryIDAndUpdateChildren_DeletedAndUnsyncedChild) { 10530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch TestIdFactory id_factory; 10540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id orig_parent_id; 10550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id orig_child_id; 10560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 10580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create two client-side items, a parent and child. 10590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 10600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent(&trans, CREATE, BOOKMARKS, id_factory.root(), "parent"); 10620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsDir(true); 10630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsUnsynced(true); 10640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry child(&trans, CREATE, BOOKMARKS, parent.GetId(), "child"); 10660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutIsUnsynced(true); 10670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch orig_parent_id = parent.GetId(); 10690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch orig_child_id = child.GetId(); 10700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 10710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 10730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Delete the child. 10740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 10750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry child(&trans, GET_BY_ID, orig_child_id); 10770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutIsDel(true); 10780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 10790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 10810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Simulate what happens after committing the parent. Its ID will be 10820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // replaced with server a ID. 10830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 10840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent(&trans, GET_BY_ID, orig_parent_id); 10860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ChangeEntryIDAndUpdateChildren(&trans, &parent, id_factory.NewServerId()); 10880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsUnsynced(false); 10890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutBaseVersion(1); 10900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutServerVersion(1); 10910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 10920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Final check for validity. 10940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(OPENED, SimulateSaveAndReloadDir()); 10950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 10960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Ask the directory to generate a unique ID. Close and re-open the database 10980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// without saving, then ask for another unique ID. Verify IDs are not reused. 10990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// This scenario simulates a crash within the first few seconds of operation. 11000529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, LocalIdReuseTest) { 11010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id pre_crash_id = dir()->NextId(); 11020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SimulateCrashAndReloadDir(); 11030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id post_crash_id = dir()->NextId(); 11040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_NE(pre_crash_id, post_crash_id); 11050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 11060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Ask the directory to generate a unique ID. Save the directory. Close and 11080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// re-open the database without saving, then ask for another unique ID. Verify 11090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// IDs are not reused. This scenario simulates a steady-state crash. 11100529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, LocalIdReuseTestWithSave) { 11110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id pre_crash_id = dir()->NextId(); 11120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SaveChanges(); 11130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SimulateCrashAndReloadDir(); 11140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id post_crash_id = dir()->NextId(); 11150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_NE(pre_crash_id, post_crash_id); 11160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 11170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Ensure that the unsynced, is_del and server unkown entries that may have been 11190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// left in the database by old clients will be deleted when we open the old 11200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// database. 11210529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, OldClientLeftUnsyncedDeletedLocalItem) { 11220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // We must create an entry with the offending properties. This is done with 11230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // some abuse of the MutableEntry's API; it doesn't expect us to modify an 11240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // item after it is deleted. If this hack becomes impractical we will need to 11250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // find a new way to simulate this scenario. 11260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch TestIdFactory id_factory; 11280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Happy-path: These valid entries should not get deleted. 11300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id server_knows_id = id_factory.NewServerId(); 11310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id not_is_del_id = id_factory.NewLocalId(); 11320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The ID of the entry which will be unsynced, is_del and !ServerKnows(). 11340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id zombie_id = id_factory.NewLocalId(); 11350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // We're about to do some bad things. Tell the directory verification 11370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // routines to look the other way. 11380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->SetInvariantCheckLevel(OFF); 11390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 11410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 11420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create an uncommitted tombstone entry. 11440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry server_knows( 11450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &trans, CREATE, BOOKMARKS, id_factory.root(), "server_knows"); 11460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_knows.PutId(server_knows_id); 11470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_knows.PutIsUnsynced(true); 11480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_knows.PutIsDel(true); 11490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_knows.PutBaseVersion(5); 11500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch server_knows.PutServerVersion(4); 11510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create a valid update entry. 11530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry not_is_del( 11540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &trans, CREATE, BOOKMARKS, id_factory.root(), "not_is_del"); 11550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch not_is_del.PutId(not_is_del_id); 11560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch not_is_del.PutIsDel(false); 11570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch not_is_del.PutIsUnsynced(true); 11580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Create a tombstone which should never be sent to the server because the 11600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // server never knew about the item's existence. 11610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // 11620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // New clients should never put entries into this state. We work around 11630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // this by setting IS_DEL before setting IS_UNSYNCED, something which the 11640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // client should never do in practice. 11650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry zombie(&trans, CREATE, BOOKMARKS, id_factory.root(), "zombie"); 11660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch zombie.PutId(zombie_id); 11670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch zombie.PutIsDel(true); 11680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch zombie.PutIsUnsynced(true); 11690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 11700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(OPENED, SimulateSaveAndReloadDir()); 11720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 11740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadTransaction trans(FROM_HERE, dir().get()); 11750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The directory loading routines should have cleaned things up, making it 11770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // safe to check invariants once again. 11780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dir()->FullyCheckTreeInvariants(&trans); 11790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry server_knows(&trans, GET_BY_ID, server_knows_id); 11810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(server_knows.good()); 11820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry not_is_del(&trans, GET_BY_ID, not_is_del_id); 11840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(not_is_del.good()); 11850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry zombie(&trans, GET_BY_ID, zombie_id); 11870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_FALSE(zombie.good()); 11880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 11890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 11900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 11910529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(SyncableDirectoryTest, PositionWithNullSurvivesSaveAndReload) { 11920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch TestIdFactory id_factory; 11930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Id null_child_id; 11940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const char null_cstr[] = "\0null\0test"; 11950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string null_str(null_cstr, arraysize(null_cstr) - 1); 11960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Pad up to the minimum length with 0x7f characters, then add a string that 11970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // contains a few NULLs to the end. This is slightly wrong, since the suffix 11980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // part of a UniquePosition shouldn't contain NULLs, but it's good enough for 11990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // this test. 12000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string suffix = 12010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::string(UniquePosition::kSuffixLength - null_str.length(), '\x7f') + 12020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch null_str; 12030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch UniquePosition null_pos = UniquePosition::FromInt64(10, suffix); 12040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 12050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 12060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 12070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 12080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry parent(&trans, CREATE, BOOKMARKS, id_factory.root(), "parent"); 12090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsDir(true); 12100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent.PutIsUnsynced(true); 12110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 12120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MutableEntry child(&trans, CREATE, BOOKMARKS, parent.GetId(), "child"); 12130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutIsUnsynced(true); 12140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutUniquePosition(null_pos); 12150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch child.PutServerUniquePosition(null_pos); 12160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 12170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch null_child_id = child.GetId(); 12180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 12190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 12200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_EQ(OPENED, SimulateSaveAndReloadDir()); 12210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 12220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 12230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadTransaction trans(FROM_HERE, dir().get()); 12240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 12250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Entry null_ordinal_child(&trans, GET_BY_ID, null_child_id); 12260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(null_pos.Equals(null_ordinal_child.GetUniquePosition())); 12270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(null_pos.Equals(null_ordinal_child.GetServerUniquePosition())); 12280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 12290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 12300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Any item with BOOKMARKS in their local specifics should have a valid local 1232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// unique position. If there is an item in the loaded DB that does not match 1233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// this criteria, we consider the whole DB to be corrupt. 1234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SyncableDirectoryTest, BadPositionCountsAsCorruption) { 1235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TestIdFactory id_factory; 1236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) { 1238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 1239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MutableEntry parent(&trans, CREATE, BOOKMARKS, id_factory.root(), "parent"); 1241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) parent.PutIsDir(true); 1242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) parent.PutIsUnsynced(true); 1243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The code is littered with DCHECKs that try to stop us from doing what 1245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // we're about to do. Our work-around is to create a bookmark based on 1246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // a server update, then update its local specifics without updating its 1247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // local unique position. 1248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MutableEntry child( 1250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &trans, CREATE_NEW_UPDATE_ITEM, id_factory.MakeServer("child")); 1251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sync_pb::EntitySpecifics specifics; 1252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AddDefaultFieldValue(BOOKMARKS, &specifics); 1253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child.PutIsUnappliedUpdate(true); 1254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child.PutSpecifics(specifics); 1255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(child.ShouldMaintainPosition()); 1257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(!child.GetUniquePosition().IsValid()); 1258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(FAILED_DATABASE_CORRUPT, SimulateSaveAndReloadDir()); 1261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 1262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 12635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(SyncableDirectoryTest, General) { 12645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int64 written_metahandle; 12655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Id id = TestIdFactory::FromNumber(99); 12665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string name = "Jeff"; 12675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test simple read operations on an empty DB. 12685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 12695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction rtrans(FROM_HERE, dir().get()); 12705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry e(&rtrans, GET_BY_ID, id); 12715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_FALSE(e.good()); // Hasn't been written yet. 12725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 12735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Directory::Metahandles child_handles; 12745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir()->GetChildHandlesById(&rtrans, rtrans.root_id(), &child_handles); 12755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_TRUE(child_handles.empty()); 12765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 12775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 12785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test creating a new meta entry. 12795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 12805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction wtrans(FROM_HERE, UNITTEST, dir().get()); 12815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry me(&wtrans, CREATE, BOOKMARKS, wtrans.root_id(), name); 12825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(me.good()); 12835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutId(id); 12845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutBaseVersion(1); 12855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu written_metahandle = me.GetMetahandle(); 12865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 12875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 12885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test GetChildHandles* after something is now in the DB. 12895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Also check that GET_BY_ID works. 12905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 12915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction rtrans(FROM_HERE, dir().get()); 12925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry e(&rtrans, GET_BY_ID, id); 12935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(e.good()); 12945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 12955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Directory::Metahandles child_handles; 12965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir()->GetChildHandlesById(&rtrans, rtrans.root_id(), &child_handles); 12975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(1u, child_handles.size()); 12985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 12995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (Directory::Metahandles::iterator i = child_handles.begin(); 13005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu i != child_handles.end(); ++i) { 13015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(*i, written_metahandle); 13025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test writing data to an entity. Also check that GET_BY_HANDLE works. 13065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu static const char s[] = "Hello World."; 13075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 13085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 13095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry e(&trans, GET_BY_HANDLE, written_metahandle); 13105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(e.good()); 13115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PutDataAsBookmarkFavicon(&trans, &e, s, sizeof(s)); 13125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test reading back the contents that we just wrote. 13155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 13165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 13175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry e(&trans, GET_BY_HANDLE, written_metahandle); 13185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(e.good()); 13195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ExpectDataFromBookmarkFaviconEquals(&trans, &e, s, sizeof(s)); 13205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Verify it exists in the folder. 13235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 13245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction rtrans(FROM_HERE, dir().get()); 13255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(1, CountEntriesWithName(&rtrans, rtrans.root_id(), name)); 13265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Now delete it. 13295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 13305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 13315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry e(&trans, GET_BY_HANDLE, written_metahandle); 13325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu e.PutIsDel(true); 13335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(0, CountEntriesWithName(&trans, trans.root_id(), name)); 13355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir()->SaveChanges(); 13385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 13395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(SyncableDirectoryTest, ChildrenOps) { 13415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int64 written_metahandle; 13425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Id id = TestIdFactory::FromNumber(99); 13435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string name = "Jeff"; 13445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 13455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction rtrans(FROM_HERE, dir().get()); 13465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry e(&rtrans, GET_BY_ID, id); 13475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_FALSE(e.good()); // Hasn't been written yet. 13485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry root(&rtrans, GET_BY_ID, rtrans.root_id()); 13505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(root.good()); 13515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(dir()->HasChildren(&rtrans, rtrans.root_id())); 13525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_TRUE(root.GetFirstChildId().IsRoot()); 13535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 13565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction wtrans(FROM_HERE, UNITTEST, dir().get()); 13575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry me(&wtrans, CREATE, BOOKMARKS, wtrans.root_id(), name); 13585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(me.good()); 13595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutId(id); 13605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutBaseVersion(1); 13615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu written_metahandle = me.GetMetahandle(); 13625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test children ops after something is now in the DB. 13655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 13665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction rtrans(FROM_HERE, dir().get()); 13675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry e(&rtrans, GET_BY_ID, id); 13685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(e.good()); 13695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry child(&rtrans, GET_BY_HANDLE, written_metahandle); 13715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(child.good()); 13725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry root(&rtrans, GET_BY_ID, rtrans.root_id()); 13745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(root.good()); 13755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_TRUE(dir()->HasChildren(&rtrans, rtrans.root_id())); 13765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(e.GetId(), root.GetFirstChildId()); 13775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 13805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction wtrans(FROM_HERE, UNITTEST, dir().get()); 13815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry me(&wtrans, GET_BY_HANDLE, written_metahandle); 13825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(me.good()); 13835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutIsDel(true); 13845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test children ops after the children have been deleted. 13875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 13885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction rtrans(FROM_HERE, dir().get()); 13895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry e(&rtrans, GET_BY_ID, id); 13905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(e.good()); 13915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry root(&rtrans, GET_BY_ID, rtrans.root_id()); 13935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(root.good()); 13945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(dir()->HasChildren(&rtrans, rtrans.root_id())); 13955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_TRUE(root.GetFirstChildId().IsRoot()); 13965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 13975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 13985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir()->SaveChanges(); 13995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 14005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(SyncableDirectoryTest, ClientIndexRebuildsProperly) { 14025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int64 written_metahandle; 14035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu TestIdFactory factory; 14045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Id id = factory.NewServerId(); 14055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string name = "cheesepuffs"; 14065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string tag = "dietcoke"; 14075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test creating a new meta entry. 14095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 14105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction wtrans(FROM_HERE, UNITTEST, dir().get()); 14115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry me(&wtrans, CREATE, BOOKMARKS, wtrans.root_id(), name); 14125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(me.good()); 14135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutId(id); 14145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutBaseVersion(1); 14155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutUniqueClientTag(tag); 14165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu written_metahandle = me.GetMetahandle(); 14175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 14185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir()->SaveChanges(); 14195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Close and reopen, causing index regeneration. 14215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReopenDirectory(); 14225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 14235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction trans(FROM_HERE, dir().get()); 14245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry me(&trans, GET_BY_CLIENT_TAG, tag); 14255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(me.good()); 14265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(me.GetId(), id); 14275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(me.GetBaseVersion(), 1); 14285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(me.GetUniqueClientTag(), tag); 14295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(me.GetMetahandle(), written_metahandle); 14305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 14315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 14325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(SyncableDirectoryTest, ClientIndexRebuildsDeletedProperly) { 14345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu TestIdFactory factory; 14355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Id id = factory.NewServerId(); 14365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string tag = "dietcoke"; 14375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test creating a deleted, unsynced, server meta entry. 14395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 14405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction wtrans(FROM_HERE, UNITTEST, dir().get()); 14415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry me(&wtrans, CREATE, BOOKMARKS, wtrans.root_id(), "deleted"); 14425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(me.good()); 14435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutId(id); 14445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutBaseVersion(1); 14455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutUniqueClientTag(tag); 14465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutIsDel(true); 14475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutIsUnsynced(true); // Or it might be purged. 14485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 14495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir()->SaveChanges(); 14505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Close and reopen, causing index regeneration. 14525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReopenDirectory(); 14535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 14545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction trans(FROM_HERE, dir().get()); 14555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry me(&trans, GET_BY_CLIENT_TAG, tag); 14565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Should still be present and valid in the client tag index. 14575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(me.good()); 14585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(me.GetId(), id); 14595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(me.GetUniqueClientTag(), tag); 14605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_TRUE(me.GetIsDel()); 14615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_TRUE(me.GetIsUnsynced()); 14625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 14635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 14645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(SyncableDirectoryTest, ToValue) { 14665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Id id = TestIdFactory::FromNumber(99); 14675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 14685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction rtrans(FROM_HERE, dir().get()); 14695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Entry e(&rtrans, GET_BY_ID, id); 14705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(e.good()); // Hasn't been written yet. 14715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<base::DictionaryValue> value(e.ToValue(NULL)); 14735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ExpectDictBooleanValue(false, *value, "good"); 14745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(1u, value->size()); 14755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 14765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Test creating a new meta entry. 14785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 14795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction wtrans(FROM_HERE, UNITTEST, dir().get()); 14805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry me(&wtrans, CREATE, BOOKMARKS, wtrans.root_id(), "new"); 14815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(me.good()); 14825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutId(id); 14835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu me.PutBaseVersion(1); 14845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<base::DictionaryValue> value(me.ToValue(NULL)); 14865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ExpectDictBooleanValue(true, *value, "good"); 14875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_TRUE(value->HasKey("kernel")); 14885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ExpectDictStringValue("Bookmarks", *value, "modelType"); 14895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ExpectDictBooleanValue(true, *value, "existsOnClientBecauseNameIsNonEmpty"); 14905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ExpectDictBooleanValue(false, *value, "isRoot"); 14915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 14925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir()->SaveChanges(); 14945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 14955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 14965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Test that the bookmark tag generation algorithm remains unchanged. 14975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(SyncableDirectoryTest, BookmarkTagTest) { 14985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // This test needs its own InMemoryDirectoryBackingStore because it needs to 14995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // call request_consistent_cache_guid(). 15005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu InMemoryDirectoryBackingStore* store = new InMemoryDirectoryBackingStore("x"); 15015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The two inputs that form the bookmark tag are the directory's cache_guid 15035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // and its next_id value. We don't need to take any action to ensure 15045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // consistent next_id values, but we do need to explicitly request that our 15055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // InMemoryDirectoryBackingStore always return the same cache_guid. 15065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu store->request_consistent_cache_guid(); 15075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Directory dir(store, unrecoverable_error_handler(), NULL, NULL, NULL); 15095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ( 15105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu OPENED, 15115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir.Open("x", directory_change_delegate(), NullTransactionObserver())); 15125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 15145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction wtrans(FROM_HERE, UNITTEST, &dir); 15155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry bm(&wtrans, CREATE, BOOKMARKS, wtrans.root_id(), "bm"); 15165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bm.PutIsUnsynced(true); 15175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If this assertion fails, that might indicate that the algorithm used to 15195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // generate bookmark tags has been modified. This could have implications 15205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // for bookmark ordering. Please make sure you know what you're doing if 15215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // you intend to make such a change. 15225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_EQ("6wHRAb3kbnXV5GHrejp4/c1y5tw=", bm.GetUniqueBookmarkTag()); 15235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 15245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 15255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// A thread that creates a bunch of directory entries. 15275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass StressTransactionsDelegate : public base::PlatformThread::Delegate { 15285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public: 15295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu StressTransactionsDelegate(Directory* dir, int thread_number) 15305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : dir_(dir), thread_number_(thread_number) {} 15315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private: 15335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Directory* const dir_; 15345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const int thread_number_; 15355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // PlatformThread::Delegate methods: 15375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual void ThreadMain() OVERRIDE { 15385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int entry_count = 0; 15395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string path_name; 15405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int i = 0; i < 20; ++i) { 15425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const int rand_action = rand() % 10; 15435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (rand_action < 4 && !path_name.empty()) { 15445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ReadTransaction trans(FROM_HERE, dir_); 15455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHECK(1 == CountEntriesWithName(&trans, trans.root_id(), path_name)); 15465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::PlatformThread::Sleep( 15475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::TimeDelta::FromMilliseconds(rand() % 10)); 15485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 15495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string unique_name = 15505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::StringPrintf("%d.%d", thread_number_, entry_count++); 15515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu path_name.assign(unique_name.begin(), unique_name.end()); 15525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WriteTransaction trans(FROM_HERE, UNITTEST, dir_); 15535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MutableEntry e(&trans, CREATE, BOOKMARKS, trans.root_id(), path_name); 15545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHECK(e.good()); 15555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::PlatformThread::Sleep( 15565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::TimeDelta::FromMilliseconds(rand() % 20)); 15575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu e.PutIsUnsynced(true); 15585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (e.PutId(TestIdFactory::FromNumber(rand())) && 15595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu e.GetId().ServerKnows() && !e.GetId().IsRoot()) { 15605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu e.PutBaseVersion(1); 15615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 15625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 15635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 15645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 15655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DISALLOW_COPY_AND_ASSIGN(StressTransactionsDelegate); 15675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 15685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Stress test Directory by accessing it from several threads concurrently. 15705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(SyncableDirectoryTest, StressTransactions) { 15715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const int kThreadCount = 7; 15725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::PlatformThreadHandle threads[kThreadCount]; 15735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<StressTransactionsDelegate> thread_delegates[kThreadCount]; 15745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int i = 0; i < kThreadCount; ++i) { 15765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu thread_delegates[i].reset(new StressTransactionsDelegate(dir().get(), i)); 15775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(base::PlatformThread::Create( 15785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 0, thread_delegates[i].get(), &threads[i])); 15795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 15805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 15815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int i = 0; i < kThreadCount; ++i) { 15825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::PlatformThread::Join(threads[i]); 15835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 15845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 15855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1586010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Verify that Directory is notifed when a MutableEntry's AttachmentMetadata 1587010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// changes. 1588010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(SyncableDirectoryTest, MutableEntry_PutAttachmentMetadata) { 1589010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentMetadata attachment_metadata; 1590010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentMetadataRecord* record = attachment_metadata.add_record(); 1591010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentIdProto attachment_id_proto = 1592010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) syncer::CreateAttachmentIdProto(); 1593010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *record->mutable_id() = attachment_id_proto; 1594010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id_proto)); 1595010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) { 1596010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 1597010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1598010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Create an entry with attachment metadata and see that the attachment id 1599010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // is not linked. 1600010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MutableEntry entry( 1601010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) &trans, CREATE, PREFERENCES, trans.root_id(), "some entry"); 1602010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) entry.PutId(TestIdFactory::FromNumber(-1)); 1603010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) entry.PutIsUnsynced(true); 1604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Directory::Metahandles metahandles; 1606010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id_proto)); 1607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dir()->GetMetahandlesByAttachmentId( 1608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &trans, attachment_id_proto, &metahandles); 1609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_TRUE(metahandles.empty()); 1610010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1611010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Now add the attachment metadata and see that Directory believes it is 1612010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // linked. 1613010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) entry.PutAttachmentMetadata(attachment_metadata); 1614010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id_proto)); 1615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dir()->GetMetahandlesByAttachmentId( 1616cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &trans, attachment_id_proto, &metahandles); 1617cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(metahandles.empty()); 1618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_EQ(metahandles[0], entry.GetMetahandle()); 1619010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1620010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Clear out the attachment metadata and see that it's no longer linked. 1621010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentMetadata empty_attachment_metadata; 1622010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) entry.PutAttachmentMetadata(empty_attachment_metadata); 1623010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id_proto)); 1624cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dir()->GetMetahandlesByAttachmentId( 1625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &trans, attachment_id_proto, &metahandles); 1626cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_TRUE(metahandles.empty()); 1627010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 1628010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id_proto)); 1629010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 1630010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Verify that UpdateAttachmentId updates attachment_id and is_on_server flag. 1632cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SyncableDirectoryTest, MutableEntry_UpdateAttachmentId) { 1633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sync_pb::AttachmentMetadata attachment_metadata; 1634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sync_pb::AttachmentMetadataRecord* r1 = attachment_metadata.add_record(); 1635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sync_pb::AttachmentMetadataRecord* r2 = attachment_metadata.add_record(); 1636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *r1->mutable_id() = syncer::CreateAttachmentIdProto(); 1637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *r2->mutable_id() = syncer::CreateAttachmentIdProto(); 1638cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sync_pb::AttachmentIdProto attachment_id_proto = r1->id(); 1639cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1640cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 1641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1642cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MutableEntry entry( 1643cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &trans, CREATE, PREFERENCES, trans.root_id(), "some entry"); 1644cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.PutId(TestIdFactory::FromNumber(-1)); 1645cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.PutAttachmentMetadata(attachment_metadata); 1646cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1647cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const sync_pb::AttachmentMetadata& entry_metadata = 1648cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.GetAttachmentMetadata(); 1649cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_EQ(2, entry_metadata.record_size()); 1650cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(entry_metadata.record(0).is_on_server()); 1651cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(entry_metadata.record(1).is_on_server()); 1652cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(entry.GetIsUnsynced()); 1653cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1654116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch entry.MarkAttachmentAsOnServer(attachment_id_proto); 1655cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1656cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_TRUE(entry_metadata.record(0).is_on_server()); 1657cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(entry_metadata.record(1).is_on_server()); 1658cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_TRUE(entry.GetIsUnsynced()); 1659cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 1660cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1661010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Verify that deleted entries with attachments will retain the attachments. 1662010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(SyncableDirectoryTest, Directory_DeleteDoesNotUnlinkAttachments) { 1663010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentMetadata attachment_metadata; 1664010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentMetadataRecord* record = attachment_metadata.add_record(); 1665010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentIdProto attachment_id_proto = 1666010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) syncer::CreateAttachmentIdProto(); 1667010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *record->mutable_id() = attachment_id_proto; 1668010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id_proto)); 1669010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Id id = TestIdFactory::FromNumber(-1); 1670010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1671010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Create an entry with attachment metadata and see that the attachment id 1672010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // is linked. 1673010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateEntryWithAttachmentMetadata( 1674010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) PREFERENCES, "some entry", id, attachment_metadata); 1675010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id_proto)); 1676010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1677010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Delete the entry and see that it's still linked because the entry hasn't 1678010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // yet been purged. 1679010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DeleteEntry(id); 1680010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id_proto)); 1681010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1682010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Reload the Directory, purging the deleted entry, and see that the 1683010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // attachment is no longer linked. 1684010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SimulateSaveAndReloadDir(); 1685010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id_proto)); 1686010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 1687010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1688010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Verify that a given attachment can be referenced by multiple entries and that 1689010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// any one of the references is sufficient to ensure it remains linked. 1690010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(SyncableDirectoryTest, Directory_LastReferenceUnlinksAttachments) { 1691010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Create one attachment. 1692010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentMetadata attachment_metadata; 1693010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentMetadataRecord* record = attachment_metadata.add_record(); 1694010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sync_pb::AttachmentIdProto attachment_id_proto = 1695010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) syncer::CreateAttachmentIdProto(); 1696010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *record->mutable_id() = attachment_id_proto; 1697010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1698010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Create two entries, each referencing the attachment. 1699010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Id id1 = TestIdFactory::FromNumber(-1); 1700010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Id id2 = TestIdFactory::FromNumber(-2); 1701010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateEntryWithAttachmentMetadata( 1702010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) PREFERENCES, "some entry", id1, attachment_metadata); 1703010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateEntryWithAttachmentMetadata( 1704010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) PREFERENCES, "some other entry", id2, attachment_metadata); 1705010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1706010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // See that the attachment is considered linked. 1707010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id_proto)); 1708010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1709010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Delete the first entry, reload the Directory, see that the attachment is 1710010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // still linked. 1711010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DeleteEntry(id1); 1712010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SimulateSaveAndReloadDir(); 1713010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id_proto)); 1714010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1715010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Delete the second entry, reload the Directory, see that the attachment is 1716010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // no loner linked. 1717010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DeleteEntry(id2); 1718010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SimulateSaveAndReloadDir(); 1719010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id_proto)); 1720010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 1721010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 17221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(SyncableDirectoryTest, Directory_GetAttachmentIdsToUpload) { 17231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create one attachment, referenced by two entries. 17241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AttachmentId attachment_id = AttachmentId::Create(); 17251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sync_pb::AttachmentIdProto attachment_id_proto = attachment_id.GetProto(); 17261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sync_pb::AttachmentMetadata attachment_metadata; 17271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sync_pb::AttachmentMetadataRecord* record = attachment_metadata.add_record(); 17281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *record->mutable_id() = attachment_id_proto; 17291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Id id1 = TestIdFactory::FromNumber(-1); 17301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Id id2 = TestIdFactory::FromNumber(-2); 17311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateEntryWithAttachmentMetadata( 17321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PREFERENCES, "some entry", id1, attachment_metadata); 17331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateEntryWithAttachmentMetadata( 17341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PREFERENCES, "some other entry", id2, attachment_metadata); 17351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 17361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // See that Directory reports that this attachment is not on the server. 17371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AttachmentIdSet id_set; 17381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 17391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReadTransaction trans(FROM_HERE, dir().get()); 17401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dir()->GetAttachmentIdsToUpload(&trans, PREFERENCES, &id_set); 17411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 17421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_EQ(1U, id_set.size()); 17431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_EQ(attachment_id, *id_set.begin()); 17441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 17451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Call again, but this time with a ModelType for which there are no entries. 17461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // See that Directory correctly reports that there are none. 17471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 17481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReadTransaction trans(FROM_HERE, dir().get()); 17491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dir()->GetAttachmentIdsToUpload(&trans, PASSWORDS, &id_set); 17501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 17511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(id_set.empty()); 17521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 17531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Now, mark the attachment as "on the server" via entry_1. 17541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 17551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WriteTransaction trans(FROM_HERE, UNITTEST, dir().get()); 17561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MutableEntry entry_1(&trans, GET_BY_ID, id1); 17571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci entry_1.MarkAttachmentAsOnServer(attachment_id_proto); 17581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 17591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 17601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // See that Directory no longer reports that this attachment is not on the 17611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // server. 17621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 17631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReadTransaction trans(FROM_HERE, dir().get()); 17641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dir()->GetAttachmentIdsToUpload(&trans, PREFERENCES, &id_set); 17651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 17661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(id_set.empty()); 17671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 17681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 17690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} // namespace syncable 17700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 17710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} // namespace syncer 1772