Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: sync/syncable/syncable_unittest.cc

Issue 10389103: Sync: Clear IS_UNSYNCED for deleted local items (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix check_deps issue by moving ChangeEntryIDAndUpdateChildren Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« sync/syncable/syncable.cc ('K') | « sync/syncable/syncable.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sync/syncable/syncable.h" 5 #include "sync/syncable/syncable.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/file_path.h" 10 #include "base/file_path.h"
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 422
423 virtual void SetUp() { 423 virtual void SetUp() {
424 dir_.reset(new Directory(&encryptor_, &handler_, NULL)); 424 dir_.reset(new Directory(&encryptor_, &handler_, NULL));
425 ASSERT_TRUE(dir_.get()); 425 ASSERT_TRUE(dir_.get());
426 ASSERT_EQ(OPENED, dir_->OpenInMemoryForTest(kName, &delegate_, 426 ASSERT_EQ(OPENED, dir_->OpenInMemoryForTest(kName, &delegate_,
427 NullTransactionObserver())); 427 NullTransactionObserver()));
428 ASSERT_TRUE(dir_->good()); 428 ASSERT_TRUE(dir_->good());
429 } 429 }
430 430
431 virtual void TearDown() { 431 virtual void TearDown() {
432 dir_->SaveChanges(); 432 if (dir_.get())
433 dir_->SaveChanges();
433 dir_.reset(); 434 dir_.reset();
434 } 435 }
435 436
436 void GetAllMetaHandles(BaseTransaction* trans, MetahandleSet* result) { 437 void GetAllMetaHandles(BaseTransaction* trans, MetahandleSet* result) {
437 dir_->GetAllMetaHandles(trans, result); 438 dir_->GetAllMetaHandles(trans, result);
438 } 439 }
439 440
440 bool IsInDirtyMetahandles(int64 metahandle) { 441 bool IsInDirtyMetahandles(int64 metahandle) {
441 return 1 == dir_->kernel_->dirty_metahandles->count(metahandle); 442 return 1 == dir_->kernel_->dirty_metahandles->count(metahandle);
442 } 443 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 me.Put(IS_UNSYNCED, true); 502 me.Put(IS_UNSYNCED, true);
502 } 503 }
503 504
504 void ValidateEntry(BaseTransaction* trans, 505 void ValidateEntry(BaseTransaction* trans,
505 int64 id, 506 int64 id,
506 bool check_name, 507 bool check_name,
507 const std::string& name, 508 const std::string& name,
508 int64 base_version, 509 int64 base_version,
509 int64 server_version, 510 int64 server_version,
510 bool is_del); 511 bool is_del);
512
513 // When a directory is saved then loaded from disk, it will pass through
514 // DropDeletedEntries(). This will remove some entries from the directory.
515 // This function is intended to simulate that process.
516 //
517 // WARNING: The directory will be deleted by this operation. You should
518 // not have any pointers to the directory (open transactions included)
519 // when you call this.
520 DirOpenResult SimulateSaveAndReloadDir();
511 }; 521 };
512 522
513 TEST_F(SyncableDirectoryTest, TakeSnapshotGetsMetahandlesToPurge) { 523 TEST_F(SyncableDirectoryTest, TakeSnapshotGetsMetahandlesToPurge) {
514 const int metas_to_create = 50; 524 const int metas_to_create = 50;
515 MetahandleSet expected_purges; 525 MetahandleSet expected_purges;
516 MetahandleSet all_handles; 526 MetahandleSet all_handles;
517 { 527 {
518 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get()); 528 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
519 for (int i = 0; i < metas_to_create; i++) { 529 for (int i = 0; i < metas_to_create; i++) {
520 MutableEntry e(&trans, CREATE, trans.root_id(), "foo"); 530 MutableEntry e(&trans, CREATE, trans.root_id(), "foo");
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 1157
1148 browser_sync::SyncEntity item_entity; 1158 browser_sync::SyncEntity item_entity;
1149 item_entity.set_id(id_factory.NewServerId()); 1159 item_entity.set_id(id_factory.NewServerId());
1150 item_entity.set_deleted(false); 1160 item_entity.set_deleted(false);
1151 item_entity.set_folder(false); 1161 item_entity.set_folder(false);
1152 item_entity.mutable_specifics()->CopyFrom(specifics); 1162 item_entity.mutable_specifics()->CopyFrom(specifics);
1153 ASSERT_EQ(datatype, item_entity.GetModelType()); 1163 ASSERT_EQ(datatype, item_entity.GetModelType());
1154 } 1164 }
1155 } 1165 }
1156 1166
1167 // A test that roughly mimics the directory interaction that occurs when a
1168 // bookmark folder and entry are created then synced for the first time. It is
1169 // a more common variant of the 'DeletedAndUnsyncedChild' scenario tested below.
1170 TEST_F(SyncableDirectoryTest, ChangeEntryIDAndUpdateChildren_ParentAndChild) {
1171 TestIdFactory id_factory;
1172 Id orig_parent_id;
1173 Id orig_child_id;
1174
1175 {
1176 // Create two client-side items, a parent and child.
1177 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1178
1179 MutableEntry parent(&trans, CREATE, id_factory.root(), "parent");
1180 parent.Put(IS_DIR, true);
1181 parent.Put(IS_UNSYNCED, true);
1182
1183 MutableEntry child(&trans, CREATE, parent.Get(ID), "child");
1184 child.Put(IS_UNSYNCED, true);
1185
1186 orig_parent_id = parent.Get(ID);
1187 orig_child_id = child.Get(ID);
1188 }
1189
1190 {
1191 // Simulate what happens after committing two items. Their IDs will be
1192 // replaced with server IDs. The child is renamed first, then the parent.
1193 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1194
1195 MutableEntry parent(&trans, GET_BY_ID, orig_parent_id);
1196 MutableEntry child(&trans, GET_BY_ID, orig_child_id);
1197
1198 ChangeEntryIDAndUpdateChildren(&trans, &child, id_factory.NewServerId());
1199 child.Put(IS_UNSYNCED, false);
1200 child.Put(BASE_VERSION, 1);
1201 child.Put(SERVER_VERSION, 1);
1202
1203 ChangeEntryIDAndUpdateChildren(&trans, &parent, id_factory.NewServerId());
1204 parent.Put(IS_UNSYNCED, false);
1205 parent.Put(BASE_VERSION, 1);
1206 parent.Put(SERVER_VERSION, 1);
1207 }
1208
1209 // Final check for validity.
1210 EXPECT_EQ(OPENED, SimulateSaveAndReloadDir());
1211 }
1212
1213 // A test based on the scenario where we create a bookmark folder and entry
1214 // locally, but with a twist. In this case, the bookmark is deleted before we
1215 // are able to sync either it or its parent folder. This scenario used to cause
1216 // directory corruption, see crbug.com/125381.
1217 TEST_F(SyncableDirectoryTest,
1218 ChangeEntryIDAndUpdateChildren_DeletedAndUnsyncedChild) {
1219 TestIdFactory id_factory;
1220 Id orig_parent_id;
1221 Id orig_child_id;
1222
1223 {
1224 // Create two client-side items, a parent and child.
1225 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1226
1227 MutableEntry parent(&trans, CREATE, id_factory.root(), "parent");
1228 parent.Put(IS_DIR, true);
1229 parent.Put(IS_UNSYNCED, true);
1230
1231 MutableEntry child(&trans, CREATE, parent.Get(ID), "child");
1232 child.Put(IS_UNSYNCED, true);
1233
1234 orig_parent_id = parent.Get(ID);
1235 orig_child_id = child.Get(ID);
1236 }
1237
1238 {
1239 // Delete the child.
1240 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1241
1242 MutableEntry child(&trans, GET_BY_ID, orig_child_id);
1243 child.Put(IS_DEL, true);
1244 }
1245
1246 {
1247 // Simulate what happens after committing the parent. Its ID will be
1248 // replaced with server a ID.
1249 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1250
1251 MutableEntry parent(&trans, GET_BY_ID, orig_parent_id);
1252
1253 ChangeEntryIDAndUpdateChildren(&trans, &parent, id_factory.NewServerId());
1254 parent.Put(IS_UNSYNCED, false);
1255 parent.Put(BASE_VERSION, 1);
1256 parent.Put(SERVER_VERSION, 1);
1257 }
1258
1259 // Final check for validity.
1260 EXPECT_EQ(OPENED, SimulateSaveAndReloadDir());
1261 }
1262
1157 // A variant of SyncableDirectoryTest that uses a real sqlite database. 1263 // A variant of SyncableDirectoryTest that uses a real sqlite database.
1158 class OnDiskSyncableDirectoryTest : public SyncableDirectoryTest { 1264 class OnDiskSyncableDirectoryTest : public SyncableDirectoryTest {
1159 protected: 1265 protected:
1160 // SetUp() is called before each test case is run. 1266 // SetUp() is called before each test case is run.
1161 // The sqlite3 DB is deleted before each test is run. 1267 // The sqlite3 DB is deleted before each test is run.
1162 virtual void SetUp() { 1268 virtual void SetUp() {
1163 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 1269 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
1164 file_path_ = temp_dir_.path().Append( 1270 file_path_ = temp_dir_.path().Append(
1165 FILE_PATH_LITERAL("Test.sqlite3")); 1271 FILE_PATH_LITERAL("Test.sqlite3"));
1166 file_util::Delete(file_path_, true); 1272 file_util::Delete(file_path_, true);
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
1529 bool is_del) { 1635 bool is_del) {
1530 Entry e(trans, GET_BY_ID, TestIdFactory::FromNumber(id)); 1636 Entry e(trans, GET_BY_ID, TestIdFactory::FromNumber(id));
1531 ASSERT_TRUE(e.good()); 1637 ASSERT_TRUE(e.good());
1532 if (check_name) 1638 if (check_name)
1533 ASSERT_TRUE(name == e.Get(NON_UNIQUE_NAME)); 1639 ASSERT_TRUE(name == e.Get(NON_UNIQUE_NAME));
1534 ASSERT_TRUE(base_version == e.Get(BASE_VERSION)); 1640 ASSERT_TRUE(base_version == e.Get(BASE_VERSION));
1535 ASSERT_TRUE(server_version == e.Get(SERVER_VERSION)); 1641 ASSERT_TRUE(server_version == e.Get(SERVER_VERSION));
1536 ASSERT_TRUE(is_del == e.Get(IS_DEL)); 1642 ASSERT_TRUE(is_del == e.Get(IS_DEL));
1537 } 1643 }
1538 1644
1645 DirOpenResult SyncableDirectoryTest::SimulateSaveAndReloadDir() {
1646 if (!dir_->SaveChanges())
1647 return FAILED_IN_UNITTEST;
1648
1649 // Do some tricky things to preserve the backing store.
1650 DirectoryBackingStore* saved_store = dir_->store_;
1651 dir_->store_ = NULL;
1652
1653 // Close the current directory.
1654 dir_->Close();
1655 dir_.reset();
1656
1657 dir_.reset(new Directory(&encryptor_, &handler_, NULL));
1658 if (!dir_.get())
1659 return FAILED_IN_UNITTEST;
1660 DirOpenResult result = dir_->OpenImpl(saved_store, kName, &delegate_,
1661 NullTransactionObserver());
1662
1663 // If something went wrong, we need to clear this member. If we don't,
1664 // TearDown() will be guaranteed to crash when it calls SaveChanges().
1665 if (result != OPENED)
1666 dir_.reset();
1667
1668 return result;
1669 }
1670
1539 namespace { 1671 namespace {
1540 1672
1541 class SyncableDirectoryManagement : public testing::Test { 1673 class SyncableDirectoryManagement : public testing::Test {
1542 public: 1674 public:
1543 virtual void SetUp() { 1675 virtual void SetUp() {
1544 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 1676 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
1545 } 1677 }
1546 1678
1547 virtual void TearDown() { 1679 virtual void TearDown() {
1548 } 1680 }
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1732 TEST_F(SyncableClientTagTest, TestClientTagIndexDuplicateServer) { 1864 TEST_F(SyncableClientTagTest, TestClientTagIndexDuplicateServer) {
1733 EXPECT_TRUE(CreateWithDefaultTag(factory_.NewServerId(), true)); 1865 EXPECT_TRUE(CreateWithDefaultTag(factory_.NewServerId(), true));
1734 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewServerId(), true)); 1866 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewServerId(), true));
1735 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewServerId(), false)); 1867 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewServerId(), false));
1736 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewLocalId(), false)); 1868 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewLocalId(), false));
1737 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewLocalId(), true)); 1869 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewLocalId(), true));
1738 } 1870 }
1739 1871
1740 } // namespace 1872 } // namespace
1741 } // namespace syncable 1873 } // namespace syncable
OLDNEW
« sync/syncable/syncable.cc ('K') | « sync/syncable/syncable.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698