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

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: 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"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop.h" 15 #include "base/message_loop.h"
16 #include "base/scoped_temp_dir.h" 16 #include "base/scoped_temp_dir.h"
17 #include "base/stringprintf.h" 17 #include "base/stringprintf.h"
18 #include "base/synchronization/condition_variable.h" 18 #include "base/synchronization/condition_variable.h"
19 #include "base/test/values_test_util.h" 19 #include "base/test/values_test_util.h"
20 #include "base/threading/platform_thread.h" 20 #include "base/threading/platform_thread.h"
21 #include "base/values.h" 21 #include "base/values.h"
22 #include "sync/engine/syncproto.h" 22 #include "sync/engine/syncproto.h"
23 #include "sync/engine/syncer_util.h"
rlarocque 2012/05/11 22:41:26 I'm not sure if it's OK to test syncer_util functi
23 #include "sync/util/test_unrecoverable_error_handler.h" 24 #include "sync/util/test_unrecoverable_error_handler.h"
24 #include "sync/syncable/directory_backing_store.h" 25 #include "sync/syncable/directory_backing_store.h"
25 #include "sync/syncable/directory_change_delegate.h" 26 #include "sync/syncable/directory_change_delegate.h"
26 #include "sync/syncable/on_disk_directory_backing_store.h" 27 #include "sync/syncable/on_disk_directory_backing_store.h"
27 #include "sync/test/engine/test_id_factory.h" 28 #include "sync/test/engine/test_id_factory.h"
28 #include "sync/test/engine/test_syncable_utils.h" 29 #include "sync/test/engine/test_syncable_utils.h"
29 #include "sync/test/fake_encryptor.h" 30 #include "sync/test/fake_encryptor.h"
30 #include "sync/test/null_directory_change_delegate.h" 31 #include "sync/test/null_directory_change_delegate.h"
31 #include "sync/test/null_transaction_observer.h" 32 #include "sync/test/null_transaction_observer.h"
32 #include "sync/protocol/bookmark_specifics.pb.h" 33 #include "sync/protocol/bookmark_specifics.pb.h"
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 423
423 virtual void SetUp() { 424 virtual void SetUp() {
424 dir_.reset(new Directory(&encryptor_, &handler_, NULL)); 425 dir_.reset(new Directory(&encryptor_, &handler_, NULL));
425 ASSERT_TRUE(dir_.get()); 426 ASSERT_TRUE(dir_.get());
426 ASSERT_EQ(OPENED, dir_->OpenInMemoryForTest(kName, &delegate_, 427 ASSERT_EQ(OPENED, dir_->OpenInMemoryForTest(kName, &delegate_,
427 NullTransactionObserver())); 428 NullTransactionObserver()));
428 ASSERT_TRUE(dir_->good()); 429 ASSERT_TRUE(dir_->good());
429 } 430 }
430 431
431 virtual void TearDown() { 432 virtual void TearDown() {
432 dir_->SaveChanges(); 433 if (dir_.get())
434 dir_->SaveChanges();
433 dir_.reset(); 435 dir_.reset();
434 } 436 }
435 437
436 void GetAllMetaHandles(BaseTransaction* trans, MetahandleSet* result) { 438 void GetAllMetaHandles(BaseTransaction* trans, MetahandleSet* result) {
437 dir_->GetAllMetaHandles(trans, result); 439 dir_->GetAllMetaHandles(trans, result);
438 } 440 }
439 441
440 bool IsInDirtyMetahandles(int64 metahandle) { 442 bool IsInDirtyMetahandles(int64 metahandle) {
441 return 1 == dir_->kernel_->dirty_metahandles->count(metahandle); 443 return 1 == dir_->kernel_->dirty_metahandles->count(metahandle);
442 } 444 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 me.Put(IS_UNSYNCED, true); 503 me.Put(IS_UNSYNCED, true);
502 } 504 }
503 505
504 void ValidateEntry(BaseTransaction* trans, 506 void ValidateEntry(BaseTransaction* trans,
505 int64 id, 507 int64 id,
506 bool check_name, 508 bool check_name,
507 const std::string& name, 509 const std::string& name,
508 int64 base_version, 510 int64 base_version,
509 int64 server_version, 511 int64 server_version,
510 bool is_del); 512 bool is_del);
513
514 // When a directory is saved then loaded from disk, it will pass through
515 // DropDeletedEntries(). This will remove some entries from the directory.
516 // This function is intended to simulate that process.
517 //
518 // WARNING: The directory will be deleted by this operation. You should
519 // not have any pointers to the directory (open transactions included)
520 // when you call this.
521 DirOpenResult SimulateSaveAndReloadDir();
511 }; 522 };
512 523
513 TEST_F(SyncableDirectoryTest, TakeSnapshotGetsMetahandlesToPurge) { 524 TEST_F(SyncableDirectoryTest, TakeSnapshotGetsMetahandlesToPurge) {
514 const int metas_to_create = 50; 525 const int metas_to_create = 50;
515 MetahandleSet expected_purges; 526 MetahandleSet expected_purges;
516 MetahandleSet all_handles; 527 MetahandleSet all_handles;
517 { 528 {
518 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get()); 529 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
519 for (int i = 0; i < metas_to_create; i++) { 530 for (int i = 0; i < metas_to_create; i++) {
520 MutableEntry e(&trans, CREATE, trans.root_id(), "foo"); 531 MutableEntry e(&trans, CREATE, trans.root_id(), "foo");
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 1158
1148 browser_sync::SyncEntity item_entity; 1159 browser_sync::SyncEntity item_entity;
1149 item_entity.set_id(id_factory.NewServerId()); 1160 item_entity.set_id(id_factory.NewServerId());
1150 item_entity.set_deleted(false); 1161 item_entity.set_deleted(false);
1151 item_entity.set_folder(false); 1162 item_entity.set_folder(false);
1152 item_entity.mutable_specifics()->CopyFrom(specifics); 1163 item_entity.mutable_specifics()->CopyFrom(specifics);
1153 ASSERT_EQ(datatype, item_entity.GetModelType()); 1164 ASSERT_EQ(datatype, item_entity.GetModelType());
1154 } 1165 }
1155 } 1166 }
1156 1167
1168 // A test that roughly mimics the directory interaction that occurs when a
1169 // bookmark folder and entry are created then synced for the first time. It is
1170 // a more common variant of the 'DeletedAndUnsyncedChild' scenario tested below.
Nicolas Zea 2012/05/11 23:21:25 DeleteAndUnsyncedChild -> DeleteAnUnsyncedChild? (
rlarocque 2012/05/15 00:41:55 It's DeletedAndUnsyncedChild.
1171 TEST_F(SyncableDirectoryTest, ChangeEntryIDAndUpdateChildren_ParentAndChild) {
1172 TestIdFactory id_factory;
1173 Id orig_parent_id;
1174 Id orig_child_id;
1175
1176 {
1177 // Create two client-side items, a parent and child.
1178 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1179
1180 MutableEntry parent(&trans, CREATE, id_factory.root(), "parent");
1181 parent.Put(IS_DIR, true);
1182 parent.Put(IS_UNSYNCED, true);
1183
1184 MutableEntry child(&trans, CREATE, parent.Get(ID), "child");
1185 child.Put(IS_UNSYNCED, true);
1186
1187 orig_parent_id = parent.Get(ID);
1188 orig_child_id = child.Get(ID);
1189 }
1190
1191 {
1192 // Simulate what happens after committing two items. Their IDs will be
1193 // replaced with server IDs. The child is renamed first, then the parent.
1194 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1195
1196 MutableEntry parent(&trans, GET_BY_ID, orig_parent_id);
1197 MutableEntry child(&trans, GET_BY_ID, orig_child_id);
1198
1199 browser_sync::SyncerUtil::ChangeEntryIDAndUpdateChildren(
1200 &trans, &child, id_factory.NewServerId());
1201 child.Put(IS_UNSYNCED, false);
1202 child.Put(BASE_VERSION, 1);
1203 child.Put(SERVER_VERSION, 1);
1204
1205 browser_sync::SyncerUtil::ChangeEntryIDAndUpdateChildren(
1206 &trans, &parent, id_factory.NewServerId());
1207 parent.Put(IS_UNSYNCED, false);
1208 parent.Put(BASE_VERSION, 1);
1209 parent.Put(SERVER_VERSION, 1);
1210 }
1211
1212 // Final check of validity.
Nicolas Zea 2012/05/11 23:21:25 of -> for
rlarocque 2012/05/15 00:41:55 Done.
1213 EXPECT_EQ(OPENED, SimulateSaveAndReloadDir());
1214 }
1215
1216 // A test based on the scenario where we create a bookmark folder and entry
1217 // locally, but with a twist. In this case, the bookmark is deleted before we
1218 // are abot to sync either it or its parent folder. This scenario used to cause
Nicolas Zea 2012/05/11 23:21:25 abot -> able
rlarocque 2012/05/15 00:41:55 Done.
1219 // directory corruption, see crbug.com/125381.
1220 TEST_F(SyncableDirectoryTest,
1221 ChangeEntryIDAndUpdateChildren_DeletedAndUnsyncedChild) {
1222 TestIdFactory id_factory;
1223 Id orig_parent_id;
1224 Id orig_child_id;
1225
1226 {
1227 // Create two client-side items, a parent and child.
1228 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1229
1230 MutableEntry parent(&trans, CREATE, id_factory.root(), "parent");
1231 parent.Put(IS_DIR, true);
1232 parent.Put(IS_UNSYNCED, true);
1233
1234 MutableEntry child(&trans, CREATE, parent.Get(ID), "child");
1235 child.Put(IS_UNSYNCED, true);
1236
1237 orig_parent_id = parent.Get(ID);
1238 orig_child_id = child.Get(ID);
1239 }
1240
1241 {
1242 // Delete the child.
1243 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1244
1245 MutableEntry child(&trans, GET_BY_ID, orig_child_id);
1246 child.Put(IS_DEL, true);
1247 }
1248
1249 {
1250 // Simulate what happens after committing the parent. Its ID will be
1251 // replaced with server a ID.
1252 WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get());
1253
1254 MutableEntry parent(&trans, GET_BY_ID, orig_parent_id);
1255
1256 browser_sync::SyncerUtil::ChangeEntryIDAndUpdateChildren(
1257 &trans, &parent, id_factory.NewServerId());
1258 parent.Put(IS_UNSYNCED, false);
1259 parent.Put(BASE_VERSION, 1);
1260 parent.Put(SERVER_VERSION, 1);
1261 }
1262
1263 // Final check of validity.
Nicolas Zea 2012/05/11 23:21:25 of -> for
rlarocque 2012/05/15 00:41:55 Done.
rlarocque 2012/05/15 00:41:55 Done.
1264 EXPECT_EQ(OPENED, SimulateSaveAndReloadDir());
1265 }
1266
1157 // A variant of SyncableDirectoryTest that uses a real sqlite database. 1267 // A variant of SyncableDirectoryTest that uses a real sqlite database.
1158 class OnDiskSyncableDirectoryTest : public SyncableDirectoryTest { 1268 class OnDiskSyncableDirectoryTest : public SyncableDirectoryTest {
1159 protected: 1269 protected:
1160 // SetUp() is called before each test case is run. 1270 // SetUp() is called before each test case is run.
1161 // The sqlite3 DB is deleted before each test is run. 1271 // The sqlite3 DB is deleted before each test is run.
1162 virtual void SetUp() { 1272 virtual void SetUp() {
1163 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 1273 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
1164 file_path_ = temp_dir_.path().Append( 1274 file_path_ = temp_dir_.path().Append(
1165 FILE_PATH_LITERAL("Test.sqlite3")); 1275 FILE_PATH_LITERAL("Test.sqlite3"));
1166 file_util::Delete(file_path_, true); 1276 file_util::Delete(file_path_, true);
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
1529 bool is_del) { 1639 bool is_del) {
1530 Entry e(trans, GET_BY_ID, TestIdFactory::FromNumber(id)); 1640 Entry e(trans, GET_BY_ID, TestIdFactory::FromNumber(id));
1531 ASSERT_TRUE(e.good()); 1641 ASSERT_TRUE(e.good());
1532 if (check_name) 1642 if (check_name)
1533 ASSERT_TRUE(name == e.Get(NON_UNIQUE_NAME)); 1643 ASSERT_TRUE(name == e.Get(NON_UNIQUE_NAME));
1534 ASSERT_TRUE(base_version == e.Get(BASE_VERSION)); 1644 ASSERT_TRUE(base_version == e.Get(BASE_VERSION));
1535 ASSERT_TRUE(server_version == e.Get(SERVER_VERSION)); 1645 ASSERT_TRUE(server_version == e.Get(SERVER_VERSION));
1536 ASSERT_TRUE(is_del == e.Get(IS_DEL)); 1646 ASSERT_TRUE(is_del == e.Get(IS_DEL));
1537 } 1647 }
1538 1648
1649 DirOpenResult SyncableDirectoryTest::SimulateSaveAndReloadDir() {
1650 if (!dir_->SaveChanges())
1651 return FAILED_IN_UNITTEST;
1652
1653 // Do some tricky things to preserve the backing store.
1654 DirectoryBackingStore* saved_store = dir_->store_;
1655 dir_->store_ = NULL;
1656
1657 // Close the current directory.
1658 dir_->Close();
1659 dir_.reset();
1660
1661 dir_.reset(new Directory(&encryptor_, &handler_, NULL));
1662 if (!dir_.get())
1663 return FAILED_IN_UNITTEST;
1664 DirOpenResult result = dir_->OpenImpl(saved_store, kName, &delegate_,
1665 NullTransactionObserver());
1666
1667 // If something went wrong, we to clear this member. If we don't, TearDown()
Nicolas Zea 2012/05/11 23:21:25 we to -> we need to
rlarocque 2012/05/15 00:41:55 Done.
1668 // will be guaranteed to crash when it calls SaveChanges().
1669 if (result != OPENED)
1670 dir_.reset();
1671
1672 return result;
1673 }
1674
1539 namespace { 1675 namespace {
1540 1676
1541 class SyncableDirectoryManagement : public testing::Test { 1677 class SyncableDirectoryManagement : public testing::Test {
1542 public: 1678 public:
1543 virtual void SetUp() { 1679 virtual void SetUp() {
1544 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 1680 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
1545 } 1681 }
1546 1682
1547 virtual void TearDown() { 1683 virtual void TearDown() {
1548 } 1684 }
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1732 TEST_F(SyncableClientTagTest, TestClientTagIndexDuplicateServer) { 1868 TEST_F(SyncableClientTagTest, TestClientTagIndexDuplicateServer) {
1733 EXPECT_TRUE(CreateWithDefaultTag(factory_.NewServerId(), true)); 1869 EXPECT_TRUE(CreateWithDefaultTag(factory_.NewServerId(), true));
1734 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewServerId(), true)); 1870 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewServerId(), true));
1735 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewServerId(), false)); 1871 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewServerId(), false));
1736 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewLocalId(), false)); 1872 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewLocalId(), false));
1737 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewLocalId(), true)); 1873 EXPECT_FALSE(CreateWithDefaultTag(factory_.NewLocalId(), true));
1738 } 1874 }
1739 1875
1740 } // namespace 1876 } // namespace
1741 } // namespace syncable 1877 } // 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