syncable_service_based_bridge_unittest.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/sync/model/syncable_service_based_bridge.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/run_loop.h"
  9. #include "base/test/bind.h"
  10. #include "base/test/mock_callback.h"
  11. #include "base/test/task_environment.h"
  12. #include "components/sync/base/client_tag_hash.h"
  13. #include "components/sync/engine/data_type_activation_response.h"
  14. #include "components/sync/model/client_tag_based_model_type_processor.h"
  15. #include "components/sync/model/conflict_resolution.h"
  16. #include "components/sync/model/model_error.h"
  17. #include "components/sync/model/sync_change.h"
  18. #include "components/sync/model/sync_error_factory.h"
  19. #include "components/sync/model/syncable_service.h"
  20. #include "components/sync/protocol/entity_specifics.pb.h"
  21. #include "components/sync/test/mock_model_type_change_processor.h"
  22. #include "components/sync/test/mock_model_type_worker.h"
  23. #include "components/sync/test/model_type_store_test_util.h"
  24. #include "testing/gmock/include/gmock/gmock.h"
  25. #include "testing/gtest/include/gtest/gtest.h"
  26. namespace syncer {
  27. namespace {
  28. using testing::_;
  29. using testing::ElementsAre;
  30. using testing::Eq;
  31. using testing::Invoke;
  32. using testing::IsEmpty;
  33. using testing::NotNull;
  34. using testing::Pair;
  35. using testing::Return;
  36. const ModelType kModelType = PREFERENCES;
  37. sync_pb::EntitySpecifics GetTestSpecifics(const std::string& name = "name") {
  38. sync_pb::EntitySpecifics specifics;
  39. // Make specifics non empty, to avoid it being interpreted as a tombstone.
  40. specifics.mutable_preference()->set_name(name);
  41. return specifics;
  42. }
  43. MATCHER_P(SyncDataMatches, name, "") {
  44. return arg.IsValid() && arg.GetDataType() == kModelType &&
  45. arg.GetSpecifics().preference().name() == name;
  46. }
  47. MATCHER_P2(SyncChangeMatches, change_type, name, "") {
  48. return arg.IsValid() && change_type == arg.change_type() &&
  49. arg.sync_data().GetDataType() == kModelType &&
  50. arg.sync_data().GetSpecifics().preference().name() == name;
  51. }
  52. MATCHER_P(HasName, name, "") {
  53. return arg && arg->specifics.preference().name() == name;
  54. }
  55. class MockSyncableService : public SyncableService {
  56. public:
  57. MOCK_METHOD(void, WaitUntilReadyToSync, (base::OnceClosure done), (override));
  58. MOCK_METHOD(absl::optional<syncer::ModelError>,
  59. MergeDataAndStartSyncing,
  60. (ModelType type,
  61. const SyncDataList& initial_sync_data,
  62. std::unique_ptr<SyncChangeProcessor> sync_processor,
  63. std::unique_ptr<SyncErrorFactory> sync_error_factory),
  64. (override));
  65. MOCK_METHOD(void, StopSyncing, (ModelType type), (override));
  66. MOCK_METHOD(absl::optional<ModelError>,
  67. ProcessSyncChanges,
  68. (const base::Location& from_here,
  69. const SyncChangeList& change_list),
  70. (override));
  71. MOCK_METHOD(SyncDataList, GetAllSyncData, (ModelType type), (const override));
  72. };
  73. class SyncableServiceBasedBridgeTest : public ::testing::Test {
  74. public:
  75. SyncableServiceBasedBridgeTest(const SyncableServiceBasedBridgeTest&) =
  76. delete;
  77. SyncableServiceBasedBridgeTest& operator=(
  78. const SyncableServiceBasedBridgeTest&) = delete;
  79. protected:
  80. SyncableServiceBasedBridgeTest()
  81. : store_(ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()) {
  82. ON_CALL(syncable_service_, WaitUntilReadyToSync)
  83. .WillByDefault(
  84. Invoke([](base::OnceClosure done) { std::move(done).Run(); }));
  85. ON_CALL(syncable_service_, MergeDataAndStartSyncing)
  86. .WillByDefault(
  87. [&](ModelType type, const SyncDataList& initial_sync_data,
  88. std::unique_ptr<SyncChangeProcessor> sync_processor,
  89. std::unique_ptr<SyncErrorFactory> sync_error_factory) {
  90. start_syncing_sync_processor_ = std::move(sync_processor);
  91. return absl::nullopt;
  92. });
  93. }
  94. ~SyncableServiceBasedBridgeTest() override = default;
  95. void InitializeBridge(ModelType model_type = kModelType) {
  96. real_processor_ =
  97. std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
  98. model_type, /*dump_stack=*/base::DoNothing());
  99. mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
  100. bridge_ = std::make_unique<SyncableServiceBasedBridge>(
  101. model_type,
  102. ModelTypeStoreTestUtil::FactoryForForwardingStore(store_.get()),
  103. mock_processor_.CreateForwardingProcessor(), &syncable_service_);
  104. }
  105. void ShutdownBridge() {
  106. bridge_.reset();
  107. // The mock is still delegating to |real_processor_|, so we reset it too.
  108. ASSERT_TRUE(testing::Mock::VerifyAndClear(&mock_processor_));
  109. real_processor_.reset();
  110. }
  111. syncer::DataTypeActivationRequest GetTestActivationRequest() {
  112. syncer::DataTypeActivationRequest request;
  113. request.error_handler = mock_error_handler_.Get();
  114. request.cache_guid = "TestCacheGuid";
  115. request.authenticated_account_id = CoreAccountId("SomeAccountId");
  116. return request;
  117. }
  118. void StartSyncing() {
  119. base::RunLoop loop;
  120. real_processor_->OnSyncStarting(
  121. GetTestActivationRequest(),
  122. base::BindLambdaForTesting(
  123. [&](std::unique_ptr<syncer::DataTypeActivationResponse> response) {
  124. worker_ = std::make_unique<MockModelTypeWorker>(
  125. response->model_type_state, real_processor_.get());
  126. loop.Quit();
  127. }));
  128. loop.Run();
  129. }
  130. std::map<std::string, std::unique_ptr<EntityData>> GetAllData() {
  131. base::RunLoop loop;
  132. std::unique_ptr<DataBatch> batch;
  133. bridge_->GetAllDataForDebugging(base::BindLambdaForTesting(
  134. [&loop, &batch](std::unique_ptr<DataBatch> input_batch) {
  135. batch = std::move(input_batch);
  136. loop.Quit();
  137. }));
  138. loop.Run();
  139. EXPECT_NE(nullptr, batch);
  140. std::map<std::string, std::unique_ptr<EntityData>> storage_key_to_data;
  141. while (batch && batch->HasNext()) {
  142. storage_key_to_data.insert(batch->Next());
  143. }
  144. return storage_key_to_data;
  145. }
  146. const std::string kClientTag = "clienttag";
  147. const ClientTagHash kClientTagHash =
  148. ClientTagHash::FromUnhashed(kModelType, kClientTag);
  149. base::test::SingleThreadTaskEnvironment task_environment_;
  150. testing::NiceMock<MockSyncableService> syncable_service_;
  151. testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
  152. base::MockCallback<ModelErrorHandler> mock_error_handler_;
  153. const std::unique_ptr<ModelTypeStore> store_;
  154. std::unique_ptr<syncer::ClientTagBasedModelTypeProcessor> real_processor_;
  155. std::unique_ptr<SyncableServiceBasedBridge> bridge_;
  156. std::unique_ptr<MockModelTypeWorker> worker_;
  157. // SyncChangeProcessor received via MergeDataAndStartSyncing(), or null if it
  158. // hasn't been called.
  159. std::unique_ptr<SyncChangeProcessor> start_syncing_sync_processor_;
  160. };
  161. TEST_F(SyncableServiceBasedBridgeTest,
  162. ShouldStartSyncingWithEmptyInitialRemoteData) {
  163. // Bridge initialization alone, without sync itself starting, should not
  164. // issue calls to the syncable service.
  165. EXPECT_CALL(syncable_service_, MergeDataAndStartSyncing).Times(0);
  166. InitializeBridge();
  167. // Starting sync itself is also not sufficient, until initial remote data is
  168. // received.
  169. StartSyncing();
  170. // Once the initial data is fetched from the server,
  171. // MergeDataAndStartSyncing() should be exercised.
  172. EXPECT_CALL(
  173. syncable_service_,
  174. MergeDataAndStartSyncing(kModelType, IsEmpty(), NotNull(), NotNull()));
  175. worker_->UpdateFromServer();
  176. EXPECT_THAT(GetAllData(), IsEmpty());
  177. }
  178. TEST_F(SyncableServiceBasedBridgeTest,
  179. ShouldStartSyncingWithNonEmptyInitialRemoteData) {
  180. InitializeBridge();
  181. StartSyncing();
  182. // Once the initial data is fetched from the server,
  183. // MergeDataAndStartSyncing() should be exercised.
  184. EXPECT_CALL(syncable_service_,
  185. MergeDataAndStartSyncing(kModelType,
  186. ElementsAre(SyncDataMatches("name1")),
  187. NotNull(), NotNull()));
  188. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name1"));
  189. EXPECT_THAT(GetAllData(), ElementsAre(Pair(kClientTagHash.value(), _)));
  190. }
  191. TEST_F(SyncableServiceBasedBridgeTest, ShouldWaitUntilModelReadyToSync) {
  192. base::OnceClosure syncable_service_ready_cb;
  193. ON_CALL(syncable_service_, WaitUntilReadyToSync)
  194. .WillByDefault(Invoke([&](base::OnceClosure done) {
  195. syncable_service_ready_cb = std::move(done);
  196. }));
  197. EXPECT_CALL(mock_processor_, ModelReadyToSync).Times(0);
  198. EXPECT_CALL(syncable_service_, WaitUntilReadyToSync).Times(0);
  199. EXPECT_CALL(syncable_service_, MergeDataAndStartSyncing).Times(0);
  200. // Bridge initialization alone, without sync itself starting, should not
  201. // issue calls to the syncable service.
  202. InitializeBridge();
  203. EXPECT_CALL(syncable_service_, WaitUntilReadyToSync);
  204. // Required to initialize the store.
  205. base::RunLoop().RunUntilIdle();
  206. ASSERT_TRUE(syncable_service_ready_cb);
  207. // Sync itself starting should wait until the syncable service becomes ready,
  208. // before issuing any other call (e.g. MergeDataAndStartSyncing()).
  209. real_processor_->OnSyncStarting(GetTestActivationRequest(),
  210. base::DoNothing());
  211. // When the SyncableService gets ready, the bridge should propagate this
  212. // information to the processor.
  213. EXPECT_CALL(mock_processor_, ModelReadyToSync);
  214. std::move(syncable_service_ready_cb).Run();
  215. }
  216. TEST_F(SyncableServiceBasedBridgeTest,
  217. ShouldStopSyncableServiceIfPreviouslyStarted) {
  218. InitializeBridge();
  219. StartSyncing();
  220. worker_->UpdateFromServer();
  221. EXPECT_CALL(syncable_service_, StopSyncing(kModelType));
  222. real_processor_->OnSyncStopping(CLEAR_METADATA);
  223. EXPECT_CALL(syncable_service_, StopSyncing).Times(0);
  224. ShutdownBridge();
  225. }
  226. TEST_F(SyncableServiceBasedBridgeTest,
  227. ShouldStopSyncableServiceDuringShutdownIfPreviouslyStarted) {
  228. InitializeBridge();
  229. StartSyncing();
  230. worker_->UpdateFromServer();
  231. EXPECT_CALL(syncable_service_, StopSyncing(kModelType));
  232. ShutdownBridge();
  233. }
  234. TEST_F(SyncableServiceBasedBridgeTest,
  235. ShouldNotStopSyncableServiceIfNotPreviouslyStarted) {
  236. EXPECT_CALL(syncable_service_, StopSyncing).Times(0);
  237. InitializeBridge();
  238. StartSyncing();
  239. real_processor_->OnSyncStopping(KEEP_METADATA);
  240. }
  241. TEST_F(SyncableServiceBasedBridgeTest,
  242. ShouldNotStopSyncableServiceDuringShutdownIfNotPreviouslyStarted) {
  243. EXPECT_CALL(syncable_service_, StopSyncing).Times(0);
  244. InitializeBridge();
  245. StartSyncing();
  246. ShutdownBridge();
  247. }
  248. TEST_F(SyncableServiceBasedBridgeTest, ShouldPropagateErrorDuringStart) {
  249. // Instrument MergeDataAndStartSyncing() to return an error.
  250. ON_CALL(syncable_service_, MergeDataAndStartSyncing)
  251. .WillByDefault(Return(ModelError(FROM_HERE, "Test error")));
  252. EXPECT_CALL(mock_error_handler_, Run);
  253. InitializeBridge();
  254. StartSyncing();
  255. worker_->UpdateFromServer();
  256. // Since the syncable service failed to start, it shouldn't be stopped.
  257. EXPECT_CALL(syncable_service_, StopSyncing).Times(0);
  258. ShutdownBridge();
  259. }
  260. TEST_F(SyncableServiceBasedBridgeTest,
  261. ShouldKeepSyncingWhenSyncStoppedTemporarily) {
  262. InitializeBridge();
  263. StartSyncing();
  264. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name1"));
  265. // Stopping Sync temporarily (KEEP_METADATA) should *not* result in the
  266. // SyncableService being stopped.
  267. EXPECT_CALL(syncable_service_, StopSyncing).Times(0);
  268. real_processor_->OnSyncStopping(KEEP_METADATA);
  269. EXPECT_THAT(GetAllData(), ElementsAre(Pair(kClientTagHash.value(), _)));
  270. // Since the SyncableService wasn't stopped, it shouldn't get restarted either
  271. // when Sync starts up again.
  272. EXPECT_CALL(syncable_service_, MergeDataAndStartSyncing).Times(0);
  273. StartSyncing();
  274. // Finally, shutting down the bridge (during browser shutdown) should also
  275. // stop the SyncableService.
  276. EXPECT_CALL(syncable_service_, StopSyncing(kModelType));
  277. ShutdownBridge();
  278. }
  279. TEST_F(SyncableServiceBasedBridgeTest,
  280. ShouldStartSyncingWithPreviousDirectoryDataAfterRestart) {
  281. InitializeBridge();
  282. StartSyncing();
  283. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name1"));
  284. // Mimic restart, which shouldn't start syncing until OnSyncStarting() is
  285. // received (exercised in StartSyncing()).
  286. EXPECT_CALL(syncable_service_, MergeDataAndStartSyncing).Times(0);
  287. ShutdownBridge();
  288. InitializeBridge();
  289. EXPECT_CALL(syncable_service_,
  290. MergeDataAndStartSyncing(kModelType,
  291. ElementsAre(SyncDataMatches("name1")),
  292. NotNull(), NotNull()));
  293. StartSyncing();
  294. }
  295. TEST_F(SyncableServiceBasedBridgeTest, ShouldSupportDisableReenableSequence) {
  296. InitializeBridge();
  297. StartSyncing();
  298. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics());
  299. real_processor_->OnSyncStopping(CLEAR_METADATA);
  300. EXPECT_THAT(GetAllData(), IsEmpty());
  301. EXPECT_CALL(syncable_service_, MergeDataAndStartSyncing).Times(0);
  302. StartSyncing();
  303. EXPECT_CALL(
  304. syncable_service_,
  305. MergeDataAndStartSyncing(kModelType, IsEmpty(), NotNull(), NotNull()));
  306. worker_->UpdateFromServer();
  307. }
  308. TEST_F(SyncableServiceBasedBridgeTest,
  309. ShouldPropagateLocalEntitiesDuringMerge) {
  310. ON_CALL(syncable_service_, MergeDataAndStartSyncing)
  311. .WillByDefault([&](ModelType type, const SyncDataList& initial_sync_data,
  312. std::unique_ptr<SyncChangeProcessor> sync_processor,
  313. std::unique_ptr<SyncErrorFactory> sync_error_factory) {
  314. SyncChangeList change_list;
  315. change_list.emplace_back(
  316. FROM_HERE, SyncChange::ACTION_ADD,
  317. SyncData::CreateLocalData(kClientTag, "title", GetTestSpecifics()));
  318. const absl::optional<ModelError> error =
  319. sync_processor->ProcessSyncChanges(FROM_HERE, change_list);
  320. EXPECT_FALSE(error.has_value());
  321. return absl::nullopt;
  322. });
  323. InitializeBridge();
  324. StartSyncing();
  325. EXPECT_CALL(mock_processor_,
  326. Put(kClientTagHash.value(), NotNull(), NotNull()));
  327. worker_->UpdateFromServer();
  328. EXPECT_THAT(GetAllData(), ElementsAre(Pair(kClientTagHash.value(), _)));
  329. }
  330. TEST_F(SyncableServiceBasedBridgeTest, ShouldPropagateLocalCreation) {
  331. InitializeBridge();
  332. StartSyncing();
  333. worker_->UpdateFromServer();
  334. ASSERT_THAT(start_syncing_sync_processor_, NotNull());
  335. ASSERT_THAT(GetAllData(), IsEmpty());
  336. EXPECT_CALL(mock_processor_,
  337. Put(kClientTagHash.value(), NotNull(), NotNull()));
  338. SyncChangeList change_list;
  339. change_list.emplace_back(
  340. FROM_HERE, SyncChange::ACTION_ADD,
  341. SyncData::CreateLocalData(kClientTag, "title", GetTestSpecifics()));
  342. const absl::optional<ModelError> error =
  343. start_syncing_sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
  344. EXPECT_FALSE(error.has_value());
  345. EXPECT_THAT(GetAllData(), ElementsAre(Pair(kClientTagHash.value(), _)));
  346. }
  347. TEST_F(SyncableServiceBasedBridgeTest, ShouldPropagateLocalUpdate) {
  348. InitializeBridge();
  349. StartSyncing();
  350. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name1"));
  351. ASSERT_THAT(start_syncing_sync_processor_, NotNull());
  352. ASSERT_THAT(GetAllData(),
  353. ElementsAre(Pair(kClientTagHash.value(), HasName("name1"))));
  354. EXPECT_CALL(mock_processor_,
  355. Put(kClientTagHash.value(), NotNull(), NotNull()));
  356. SyncChangeList change_list;
  357. change_list.emplace_back(FROM_HERE, SyncChange::ACTION_UPDATE,
  358. SyncData::CreateLocalData(
  359. kClientTag, "title", GetTestSpecifics("name2")));
  360. const absl::optional<ModelError> error =
  361. start_syncing_sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
  362. EXPECT_FALSE(error.has_value());
  363. EXPECT_THAT(GetAllData(),
  364. ElementsAre(Pair(kClientTagHash.value(), HasName("name2"))));
  365. }
  366. TEST_F(SyncableServiceBasedBridgeTest, ShouldPropagateLocalDeletion) {
  367. InitializeBridge();
  368. StartSyncing();
  369. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name1"));
  370. ASSERT_THAT(start_syncing_sync_processor_, NotNull());
  371. ASSERT_THAT(GetAllData(),
  372. ElementsAre(Pair(kClientTagHash.value(), HasName("name1"))));
  373. EXPECT_CALL(mock_processor_, Delete(kClientTagHash.value(), NotNull()));
  374. SyncChangeList change_list;
  375. change_list.emplace_back(FROM_HERE, SyncChange::ACTION_DELETE,
  376. SyncData::CreateLocalDelete(kClientTag, kModelType));
  377. const absl::optional<ModelError> error =
  378. start_syncing_sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
  379. EXPECT_FALSE(error.has_value());
  380. EXPECT_THAT(GetAllData(), IsEmpty());
  381. }
  382. TEST_F(SyncableServiceBasedBridgeTest,
  383. ShouldIgnoreLocalCreationIfPreviousError) {
  384. EXPECT_CALL(mock_processor_, Put).Times(0);
  385. InitializeBridge();
  386. StartSyncing();
  387. worker_->UpdateFromServer();
  388. ASSERT_THAT(start_syncing_sync_processor_, NotNull());
  389. ASSERT_THAT(GetAllData(), IsEmpty());
  390. // We fake an error, reported by the bridge.
  391. EXPECT_CALL(mock_error_handler_, Run);
  392. real_processor_->ReportError(ModelError(FROM_HERE, "Fake error"));
  393. ASSERT_TRUE(real_processor_->GetError());
  394. // Further local changes should be ignored.
  395. SyncChangeList change_list;
  396. change_list.emplace_back(
  397. FROM_HERE, SyncChange::ACTION_ADD,
  398. SyncData::CreateLocalData(kClientTag, "title", GetTestSpecifics()));
  399. const absl::optional<ModelError> error =
  400. start_syncing_sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
  401. EXPECT_TRUE(error.has_value());
  402. EXPECT_THAT(GetAllData(), IsEmpty());
  403. }
  404. TEST_F(SyncableServiceBasedBridgeTest, ShouldPropagateRemoteCreation) {
  405. InitializeBridge();
  406. StartSyncing();
  407. worker_->UpdateFromServer();
  408. ASSERT_THAT(start_syncing_sync_processor_, NotNull());
  409. ASSERT_THAT(GetAllData(), IsEmpty());
  410. EXPECT_CALL(syncable_service_,
  411. ProcessSyncChanges(_, ElementsAre(SyncChangeMatches(
  412. SyncChange::ACTION_ADD, "name1"))));
  413. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name1"));
  414. EXPECT_THAT(GetAllData(),
  415. ElementsAre(Pair(kClientTagHash.value(), HasName("name1"))));
  416. }
  417. TEST_F(SyncableServiceBasedBridgeTest, ShouldPropagateRemoteUpdates) {
  418. InitializeBridge();
  419. StartSyncing();
  420. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name1"));
  421. ASSERT_THAT(start_syncing_sync_processor_, NotNull());
  422. ASSERT_THAT(GetAllData(),
  423. ElementsAre(Pair(kClientTagHash.value(), HasName("name1"))));
  424. EXPECT_CALL(syncable_service_,
  425. ProcessSyncChanges(_, ElementsAre(SyncChangeMatches(
  426. SyncChange::ACTION_UPDATE, "name2"))));
  427. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name2"));
  428. EXPECT_THAT(GetAllData(),
  429. ElementsAre(Pair(kClientTagHash.value(), HasName("name2"))));
  430. // A second update for the same entity.
  431. EXPECT_CALL(syncable_service_,
  432. ProcessSyncChanges(_, ElementsAre(SyncChangeMatches(
  433. SyncChange::ACTION_UPDATE, "name3"))));
  434. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name3"));
  435. EXPECT_THAT(GetAllData(),
  436. ElementsAre(Pair(kClientTagHash.value(), HasName("name3"))));
  437. }
  438. TEST_F(SyncableServiceBasedBridgeTest, ShouldPropagateRemoteDeletion) {
  439. InitializeBridge();
  440. StartSyncing();
  441. worker_->UpdateFromServer(kClientTagHash, GetTestSpecifics("name1"));
  442. ASSERT_THAT(start_syncing_sync_processor_, NotNull());
  443. ASSERT_THAT(GetAllData(),
  444. ElementsAre(Pair(kClientTagHash.value(), HasName("name1"))));
  445. EXPECT_CALL(syncable_service_,
  446. ProcessSyncChanges(_, ElementsAre(SyncChangeMatches(
  447. SyncChange::ACTION_DELETE, "name1"))));
  448. worker_->TombstoneFromServer(kClientTagHash);
  449. EXPECT_THAT(GetAllData(), IsEmpty());
  450. }
  451. TEST(SyncableServiceBasedBridgeLocalChangeProcessorTest,
  452. ShouldDropIfCommitted) {
  453. const std::string kClientTagHash = "clienttaghash1";
  454. base::test::SingleThreadTaskEnvironment task_environment;
  455. std::unique_ptr<ModelTypeStore> store =
  456. ModelTypeStoreTestUtil::CreateInMemoryStoreForTest();
  457. SyncableServiceBasedBridge::InMemoryStore in_memory_store;
  458. testing::NiceMock<MockModelTypeChangeProcessor> mock_processor;
  459. in_memory_store[kClientTagHash] = sync_pb::EntitySpecifics();
  460. std::unique_ptr<SyncChangeProcessor> sync_change_processor =
  461. SyncableServiceBasedBridge::CreateLocalChangeProcessorForTesting(
  462. HISTORY_DELETE_DIRECTIVES, store.get(), &in_memory_store,
  463. &mock_processor);
  464. EXPECT_CALL(mock_processor, IsEntityUnsynced(kClientTagHash))
  465. .WillOnce(Return(false));
  466. EXPECT_CALL(mock_processor, UntrackEntityForStorageKey(kClientTagHash));
  467. sync_pb::EntitySpecifics specifics;
  468. specifics.mutable_history_delete_directive();
  469. SyncChangeList change_list;
  470. change_list.push_back(
  471. SyncChange(FROM_HERE, SyncChange::ACTION_DELETE,
  472. SyncData::CreateRemoteData(
  473. specifics, ClientTagHash::FromHashed(kClientTagHash))));
  474. sync_change_processor->ProcessSyncChanges(FROM_HERE, change_list);
  475. EXPECT_EQ(0U, in_memory_store.count(kClientTagHash));
  476. }
  477. TEST(SyncableServiceBasedBridgeLocalChangeProcessorTest,
  478. ShouldNotDropIfUnsynced) {
  479. const std::string kClientTagHash = "clienttaghash1";
  480. base::test::SingleThreadTaskEnvironment task_environment;
  481. std::unique_ptr<ModelTypeStore> store =
  482. ModelTypeStoreTestUtil::CreateInMemoryStoreForTest();
  483. SyncableServiceBasedBridge::InMemoryStore in_memory_store;
  484. testing::NiceMock<MockModelTypeChangeProcessor> mock_processor;
  485. in_memory_store[kClientTagHash] = sync_pb::EntitySpecifics();
  486. std::unique_ptr<SyncChangeProcessor> sync_change_processor =
  487. SyncableServiceBasedBridge::CreateLocalChangeProcessorForTesting(
  488. HISTORY_DELETE_DIRECTIVES, store.get(), &in_memory_store,
  489. &mock_processor);
  490. EXPECT_CALL(mock_processor, IsEntityUnsynced(kClientTagHash))
  491. .WillOnce(Return(true));
  492. EXPECT_CALL(mock_processor, UntrackEntityForStorageKey).Times(0);
  493. sync_pb::EntitySpecifics specifics;
  494. specifics.mutable_history_delete_directive();
  495. SyncChangeList change_list;
  496. change_list.push_back(
  497. SyncChange(FROM_HERE, SyncChange::ACTION_DELETE,
  498. SyncData::CreateRemoteData(
  499. specifics, ClientTagHash::FromHashed(kClientTagHash))));
  500. sync_change_processor->ProcessSyncChanges(FROM_HERE, change_list);
  501. EXPECT_EQ(1U, in_memory_store.count(kClientTagHash));
  502. }
  503. TEST_F(SyncableServiceBasedBridgeTest, ConflictShouldUseRemote) {
  504. InitializeBridge();
  505. EntityData remote_data;
  506. remote_data.client_tag_hash = kClientTagHash;
  507. remote_data.specifics = GetTestSpecifics();
  508. ASSERT_FALSE(remote_data.is_deleted());
  509. EXPECT_THAT(bridge_->ResolveConflict("storagekey1", remote_data),
  510. Eq(ConflictResolution::kUseRemote));
  511. }
  512. TEST_F(SyncableServiceBasedBridgeTest,
  513. ConflictWithRemoteDeletionShouldUseLocal) {
  514. InitializeBridge();
  515. EntityData remote_data;
  516. remote_data.client_tag_hash = kClientTagHash;
  517. ASSERT_TRUE(remote_data.is_deleted());
  518. EXPECT_THAT(bridge_->ResolveConflict("storagekey1", remote_data),
  519. Eq(ConflictResolution::kUseLocal));
  520. }
  521. // This ensures that for extensions, the conflict is resolved in favor of the
  522. // server, to prevent extensions from being reinstalled after uninstall.
  523. TEST_F(SyncableServiceBasedBridgeTest,
  524. ConflictWithRemoteExtensionUninstallShouldUseRemote) {
  525. InitializeBridge(EXTENSIONS);
  526. EntityData remote_data;
  527. remote_data.client_tag_hash = kClientTagHash;
  528. ASSERT_TRUE(remote_data.is_deleted());
  529. EXPECT_THAT(bridge_->ResolveConflict("storagekey1", remote_data),
  530. Eq(ConflictResolution::kUseRemote));
  531. }
  532. // Same as above but for APPS.
  533. TEST_F(SyncableServiceBasedBridgeTest,
  534. ConflictWithRemoteAppUninstallShouldUseRemote) {
  535. InitializeBridge(APPS);
  536. EntityData remote_data;
  537. remote_data.client_tag_hash = kClientTagHash;
  538. ASSERT_TRUE(remote_data.is_deleted());
  539. EXPECT_THAT(bridge_->ResolveConflict("storagekey1", remote_data),
  540. Eq(ConflictResolution::kUseRemote));
  541. }
  542. } // namespace
  543. } // namespace syncer