OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |