processor_entity_unittest.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. // Copyright 2014 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/processor_entity.h"
  5. #include <utility>
  6. #include "base/test/metrics/histogram_tester.h"
  7. #include "base/test/scoped_feature_list.h"
  8. #include "base/time/time.h"
  9. #include "components/sync/base/client_tag_hash.h"
  10. #include "components/sync/base/features.h"
  11. #include "components/sync/base/model_type.h"
  12. #include "components/sync/base/time.h"
  13. #include "components/sync/engine/commit_and_get_updates_types.h"
  14. #include "components/sync/protocol/entity_metadata.pb.h"
  15. #include "components/sync/protocol/entity_specifics.pb.h"
  16. #include "testing/gmock/include/gmock/gmock.h"
  17. #include "testing/gtest/include/gtest/gtest.h"
  18. namespace syncer {
  19. namespace {
  20. const char kKey[] = "key";
  21. const ClientTagHash kHash = ClientTagHash::FromHashed("hash");
  22. const char kId[] = "id";
  23. const char kName[] = "name";
  24. const char kValue1[] = "value1";
  25. const char kValue2[] = "value2";
  26. const char kValue3[] = "value3";
  27. sync_pb::EntitySpecifics GenerateSpecifics(const std::string& name,
  28. const std::string& value) {
  29. sync_pb::EntitySpecifics specifics;
  30. specifics.mutable_preference()->set_name(name);
  31. specifics.mutable_preference()->set_value(value);
  32. return specifics;
  33. }
  34. std::unique_ptr<EntityData> GenerateEntityData(const ClientTagHash& hash,
  35. const std::string& name,
  36. const std::string& value) {
  37. std::unique_ptr<EntityData> entity_data(new EntityData());
  38. entity_data->client_tag_hash = hash;
  39. entity_data->specifics = GenerateSpecifics(name, value);
  40. entity_data->name = name;
  41. return entity_data;
  42. }
  43. UpdateResponseData GenerateUpdate(const ProcessorEntity& entity,
  44. const ClientTagHash& hash,
  45. const std::string& id,
  46. const std::string& name,
  47. const std::string& value,
  48. const base::Time& mtime,
  49. int64_t version) {
  50. std::unique_ptr<EntityData> data = GenerateEntityData(hash, name, value);
  51. data->id = id;
  52. data->modification_time = mtime;
  53. UpdateResponseData update;
  54. update.entity = std::move(*data);
  55. update.response_version = version;
  56. return update;
  57. }
  58. UpdateResponseData GenerateTombstone(const ProcessorEntity& entity,
  59. const ClientTagHash& hash,
  60. const std::string& id,
  61. const std::string& name,
  62. const base::Time& mtime,
  63. int64_t version) {
  64. std::unique_ptr<EntityData> data = std::make_unique<EntityData>();
  65. data->client_tag_hash = hash;
  66. data->name = name;
  67. data->id = id;
  68. data->modification_time = mtime;
  69. UpdateResponseData update;
  70. update.entity = std::move(*data);
  71. update.response_version = version;
  72. return update;
  73. }
  74. CommitResponseData GenerateAckData(const CommitRequestData& request,
  75. const std::string id,
  76. int64_t version) {
  77. CommitResponseData response;
  78. response.id = id;
  79. response.client_tag_hash = request.entity->client_tag_hash;
  80. response.sequence_number = request.sequence_number;
  81. response.response_version = version;
  82. response.specifics_hash = request.specifics_hash;
  83. return response;
  84. }
  85. } // namespace
  86. // Some simple sanity tests for the ProcessorEntity.
  87. //
  88. // A lot of the more complicated sync logic is implemented in the
  89. // ClientTagBasedModelTypeProcessor that owns the ProcessorEntity. We
  90. // can't unit test it here.
  91. //
  92. // Instead, we focus on simple tests to make sure that variables are getting
  93. // properly intialized and flags properly set. Anything more complicated would
  94. // be a redundant and incomplete version of the ClientTagBasedModelTypeProcessor
  95. // tests.
  96. class ProcessorEntityTest : public ::testing::Test {
  97. public:
  98. ProcessorEntityTest() : ctime_(base::Time::Now() - base::Seconds(1)) {}
  99. std::unique_ptr<ProcessorEntity> CreateNew() {
  100. return ProcessorEntity::CreateNew(kKey, kHash, "", ctime_);
  101. }
  102. std::unique_ptr<ProcessorEntity> CreateNewWithEmptyStorageKey() {
  103. return ProcessorEntity::CreateNew("", kHash, "", ctime_);
  104. }
  105. std::unique_ptr<ProcessorEntity> CreateSynced() {
  106. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  107. UpdateResponseData update =
  108. GenerateUpdate(*entity, kHash, kId, kName, kValue1, ctime_, 1);
  109. entity->RecordAcceptedRemoteUpdate(update, /*trimmed_specifics=*/{});
  110. DCHECK(!entity->IsUnsynced());
  111. return entity;
  112. }
  113. std::unique_ptr<ProcessorEntity> RestoreFromMetadata(
  114. sync_pb::EntityMetadata entity_metadata) {
  115. return ProcessorEntity::CreateFromMetadata(kKey,
  116. std::move(entity_metadata));
  117. }
  118. const base::Time ctime_;
  119. };
  120. // Test the state of the default new entity.
  121. TEST_F(ProcessorEntityTest, DefaultEntity) {
  122. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  123. EXPECT_EQ(kKey, entity->storage_key());
  124. EXPECT_EQ(kHash.value(), entity->metadata().client_tag_hash());
  125. EXPECT_EQ("", entity->metadata().server_id());
  126. EXPECT_FALSE(entity->metadata().is_deleted());
  127. EXPECT_EQ(0, entity->metadata().sequence_number());
  128. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  129. EXPECT_EQ(kUncommittedVersion, entity->metadata().server_version());
  130. EXPECT_EQ(TimeToProtoTime(ctime_), entity->metadata().creation_time());
  131. EXPECT_EQ(0, entity->metadata().modification_time());
  132. EXPECT_TRUE(entity->metadata().specifics_hash().empty());
  133. EXPECT_TRUE(entity->metadata().base_specifics_hash().empty());
  134. EXPECT_FALSE(entity->IsUnsynced());
  135. EXPECT_FALSE(entity->RequiresCommitRequest());
  136. EXPECT_FALSE(entity->RequiresCommitData());
  137. EXPECT_FALSE(entity->CanClearMetadata());
  138. EXPECT_FALSE(entity->IsVersionAlreadyKnown(1));
  139. EXPECT_FALSE(entity->HasCommitData());
  140. }
  141. // Test creating and commiting a new local item.
  142. TEST_F(ProcessorEntityTest, NewLocalItem) {
  143. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  144. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue1),
  145. /*trimmed_specifics=*/{});
  146. EXPECT_EQ("", entity->metadata().server_id());
  147. EXPECT_FALSE(entity->metadata().is_deleted());
  148. EXPECT_EQ(1, entity->metadata().sequence_number());
  149. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  150. EXPECT_EQ(kUncommittedVersion, entity->metadata().server_version());
  151. EXPECT_NE(0, entity->metadata().modification_time());
  152. EXPECT_FALSE(entity->metadata().specifics_hash().empty());
  153. EXPECT_TRUE(entity->metadata().base_specifics_hash().empty());
  154. EXPECT_TRUE(entity->IsUnsynced());
  155. EXPECT_TRUE(entity->RequiresCommitRequest());
  156. EXPECT_FALSE(entity->RequiresCommitData());
  157. EXPECT_FALSE(entity->CanClearMetadata());
  158. EXPECT_FALSE(entity->IsVersionAlreadyKnown(1));
  159. EXPECT_TRUE(entity->HasCommitData());
  160. EXPECT_EQ(kValue1, entity->commit_data().specifics.preference().value());
  161. // Generate a commit request. The metadata should not change.
  162. const sync_pb::EntityMetadata metadata_v1 = entity->metadata();
  163. CommitRequestData request;
  164. entity->InitializeCommitRequestData(&request);
  165. EXPECT_EQ(metadata_v1.SerializeAsString(),
  166. entity->metadata().SerializeAsString());
  167. EXPECT_TRUE(entity->IsUnsynced());
  168. EXPECT_FALSE(entity->RequiresCommitRequest());
  169. EXPECT_FALSE(entity->RequiresCommitData());
  170. EXPECT_FALSE(entity->CanClearMetadata());
  171. EXPECT_FALSE(entity->IsVersionAlreadyKnown(1));
  172. const EntityData& data = *request.entity;
  173. EXPECT_EQ("", data.id);
  174. EXPECT_EQ(kHash, data.client_tag_hash);
  175. EXPECT_EQ(kName, data.name);
  176. EXPECT_EQ(kValue1, data.specifics.preference().value());
  177. EXPECT_EQ(TimeToProtoTime(ctime_), TimeToProtoTime(data.creation_time));
  178. EXPECT_EQ(entity->metadata().modification_time(),
  179. TimeToProtoTime(data.modification_time));
  180. EXPECT_FALSE(data.is_deleted());
  181. EXPECT_EQ(1, request.sequence_number);
  182. EXPECT_EQ(kUncommittedVersion, request.base_version);
  183. EXPECT_EQ(entity->metadata().specifics_hash(), request.specifics_hash);
  184. // Ack the commit.
  185. entity->ReceiveCommitResponse(GenerateAckData(request, kId, 1), false);
  186. EXPECT_EQ(kId, entity->metadata().server_id());
  187. EXPECT_FALSE(entity->metadata().is_deleted());
  188. EXPECT_EQ(1, entity->metadata().sequence_number());
  189. EXPECT_EQ(1, entity->metadata().acked_sequence_number());
  190. EXPECT_EQ(1, entity->metadata().server_version());
  191. EXPECT_EQ(metadata_v1.creation_time(), entity->metadata().creation_time());
  192. EXPECT_EQ(metadata_v1.modification_time(),
  193. entity->metadata().modification_time());
  194. EXPECT_FALSE(entity->metadata().specifics_hash().empty());
  195. EXPECT_TRUE(entity->metadata().base_specifics_hash().empty());
  196. EXPECT_FALSE(entity->IsUnsynced());
  197. EXPECT_FALSE(entity->RequiresCommitRequest());
  198. EXPECT_FALSE(entity->RequiresCommitData());
  199. EXPECT_FALSE(entity->CanClearMetadata());
  200. EXPECT_TRUE(entity->IsVersionAlreadyKnown(1));
  201. EXPECT_FALSE(entity->HasCommitData());
  202. }
  203. // Test state for a newly synced server item.
  204. TEST_F(ProcessorEntityTest, NewServerItem) {
  205. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  206. const base::Time mtime = base::Time::Now();
  207. UpdateResponseData update =
  208. GenerateUpdate(*entity, kHash, kId, kName, kValue1, mtime, 10);
  209. entity->RecordAcceptedRemoteUpdate(update, /*trimmed_specifics=*/{});
  210. EXPECT_EQ(kId, entity->metadata().server_id());
  211. EXPECT_FALSE(entity->metadata().is_deleted());
  212. EXPECT_EQ(0, entity->metadata().sequence_number());
  213. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  214. EXPECT_EQ(10, entity->metadata().server_version());
  215. EXPECT_EQ(TimeToProtoTime(mtime), entity->metadata().modification_time());
  216. EXPECT_FALSE(entity->metadata().specifics_hash().empty());
  217. EXPECT_TRUE(entity->metadata().base_specifics_hash().empty());
  218. EXPECT_FALSE(entity->IsUnsynced());
  219. EXPECT_FALSE(entity->RequiresCommitRequest());
  220. EXPECT_FALSE(entity->RequiresCommitData());
  221. EXPECT_FALSE(entity->CanClearMetadata());
  222. EXPECT_TRUE(entity->IsVersionAlreadyKnown(9));
  223. EXPECT_TRUE(entity->IsVersionAlreadyKnown(10));
  224. EXPECT_FALSE(entity->IsVersionAlreadyKnown(11));
  225. EXPECT_FALSE(entity->HasCommitData());
  226. }
  227. // Test creating an entity for new server item with empty storage key, applying
  228. // update and updating storage key.
  229. TEST_F(ProcessorEntityTest, NewServerItem_EmptyStorageKey) {
  230. std::unique_ptr<ProcessorEntity> entity = CreateNewWithEmptyStorageKey();
  231. EXPECT_EQ("", entity->storage_key());
  232. const base::Time mtime = base::Time::Now();
  233. UpdateResponseData update =
  234. GenerateUpdate(*entity, kHash, kId, kName, kValue1, mtime, 10);
  235. entity->RecordAcceptedRemoteUpdate(update, /*trimmed_specifics=*/{});
  236. entity->SetStorageKey(kKey);
  237. EXPECT_EQ(kKey, entity->storage_key());
  238. }
  239. // Test state for a tombstone received for a previously unknown item.
  240. TEST_F(ProcessorEntityTest, NewServerTombstone) {
  241. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  242. const base::Time mtime = base::Time::Now();
  243. UpdateResponseData tombstone =
  244. GenerateTombstone(*entity, kHash, kId, kName, mtime, 1);
  245. entity->RecordAcceptedRemoteUpdate(tombstone, /*trimmed_specifics=*/{});
  246. EXPECT_EQ(kId, entity->metadata().server_id());
  247. EXPECT_TRUE(entity->metadata().is_deleted());
  248. EXPECT_EQ(0, entity->metadata().sequence_number());
  249. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  250. EXPECT_EQ(1, entity->metadata().server_version());
  251. EXPECT_EQ(TimeToProtoTime(mtime), entity->metadata().modification_time());
  252. EXPECT_TRUE(entity->metadata().specifics_hash().empty());
  253. EXPECT_TRUE(entity->metadata().base_specifics_hash().empty());
  254. EXPECT_FALSE(entity->IsUnsynced());
  255. EXPECT_FALSE(entity->RequiresCommitRequest());
  256. EXPECT_FALSE(entity->RequiresCommitData());
  257. EXPECT_TRUE(entity->CanClearMetadata());
  258. EXPECT_TRUE(entity->IsVersionAlreadyKnown(1));
  259. EXPECT_FALSE(entity->IsVersionAlreadyKnown(2));
  260. EXPECT_FALSE(entity->HasCommitData());
  261. }
  262. // Apply a deletion update to a synced item.
  263. TEST_F(ProcessorEntityTest, ServerTombstone) {
  264. // Start with a non-deleted state with version 1.
  265. std::unique_ptr<ProcessorEntity> entity = CreateSynced();
  266. // A deletion update one version later.
  267. const base::Time mtime = base::Time::Now();
  268. UpdateResponseData tombstone =
  269. GenerateTombstone(*entity, kHash, kId, kName, mtime, 2);
  270. entity->RecordAcceptedRemoteUpdate(tombstone, /*trimmed_specifics=*/{});
  271. EXPECT_TRUE(entity->metadata().is_deleted());
  272. EXPECT_EQ(0, entity->metadata().sequence_number());
  273. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  274. EXPECT_EQ(2, entity->metadata().server_version());
  275. EXPECT_EQ(TimeToProtoTime(mtime), entity->metadata().modification_time());
  276. EXPECT_TRUE(entity->metadata().specifics_hash().empty());
  277. EXPECT_TRUE(entity->metadata().base_specifics_hash().empty());
  278. EXPECT_FALSE(entity->IsUnsynced());
  279. EXPECT_FALSE(entity->RequiresCommitRequest());
  280. EXPECT_FALSE(entity->RequiresCommitData());
  281. EXPECT_TRUE(entity->CanClearMetadata());
  282. EXPECT_TRUE(entity->IsVersionAlreadyKnown(2));
  283. EXPECT_FALSE(entity->IsVersionAlreadyKnown(3));
  284. EXPECT_FALSE(entity->HasCommitData());
  285. }
  286. // Test a local change of a synced item.
  287. TEST_F(ProcessorEntityTest, LocalChange) {
  288. std::unique_ptr<ProcessorEntity> entity = CreateSynced();
  289. const int64_t mtime_v0 = entity->metadata().modification_time();
  290. const std::string specifics_hash_v0 = entity->metadata().specifics_hash();
  291. // Make a local change with different specifics.
  292. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue2),
  293. /*trimmed_specifics=*/{});
  294. const int64_t mtime_v1 = entity->metadata().modification_time();
  295. const std::string specifics_hash_v1 = entity->metadata().specifics_hash();
  296. EXPECT_FALSE(entity->metadata().is_deleted());
  297. EXPECT_EQ(1, entity->metadata().sequence_number());
  298. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  299. EXPECT_EQ(1, entity->metadata().server_version());
  300. EXPECT_LT(mtime_v0, mtime_v1);
  301. EXPECT_NE(specifics_hash_v0, specifics_hash_v1);
  302. EXPECT_EQ(specifics_hash_v0, entity->metadata().base_specifics_hash());
  303. EXPECT_TRUE(entity->IsUnsynced());
  304. EXPECT_TRUE(entity->RequiresCommitRequest());
  305. EXPECT_FALSE(entity->RequiresCommitData());
  306. EXPECT_FALSE(entity->CanClearMetadata());
  307. EXPECT_TRUE(entity->HasCommitData());
  308. // Make a commit.
  309. CommitRequestData request;
  310. entity->InitializeCommitRequestData(&request);
  311. EXPECT_EQ(kId, request.entity->id);
  312. EXPECT_FALSE(entity->RequiresCommitRequest());
  313. // Ack the commit.
  314. entity->ReceiveCommitResponse(GenerateAckData(request, kId, 2), false);
  315. EXPECT_EQ(1, entity->metadata().sequence_number());
  316. EXPECT_EQ(1, entity->metadata().acked_sequence_number());
  317. EXPECT_EQ(2, entity->metadata().server_version());
  318. EXPECT_EQ(mtime_v1, entity->metadata().modification_time());
  319. EXPECT_EQ(specifics_hash_v1, entity->metadata().specifics_hash());
  320. EXPECT_EQ("", entity->metadata().base_specifics_hash());
  321. EXPECT_FALSE(entity->IsUnsynced());
  322. EXPECT_FALSE(entity->RequiresCommitRequest());
  323. EXPECT_FALSE(entity->RequiresCommitData());
  324. EXPECT_FALSE(entity->CanClearMetadata());
  325. EXPECT_FALSE(entity->HasCommitData());
  326. }
  327. // Test a local deletion of a synced item.
  328. TEST_F(ProcessorEntityTest, LocalDeletion) {
  329. std::unique_ptr<ProcessorEntity> entity = CreateSynced();
  330. const int64_t mtime = entity->metadata().modification_time();
  331. const std::string specifics_hash = entity->metadata().specifics_hash();
  332. // Make a local delete.
  333. entity->RecordLocalDeletion();
  334. EXPECT_TRUE(entity->metadata().is_deleted());
  335. EXPECT_EQ(1, entity->metadata().sequence_number());
  336. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  337. EXPECT_EQ(1, entity->metadata().server_version());
  338. EXPECT_LT(mtime, entity->metadata().modification_time());
  339. EXPECT_TRUE(entity->metadata().specifics_hash().empty());
  340. EXPECT_EQ(specifics_hash, entity->metadata().base_specifics_hash());
  341. EXPECT_TRUE(entity->IsUnsynced());
  342. EXPECT_TRUE(entity->RequiresCommitRequest());
  343. EXPECT_FALSE(entity->RequiresCommitData());
  344. EXPECT_FALSE(entity->CanClearMetadata());
  345. EXPECT_FALSE(entity->HasCommitData());
  346. // Generate a commit request. The metadata should not change.
  347. const sync_pb::EntityMetadata metadata_v1 = entity->metadata();
  348. CommitRequestData request;
  349. entity->InitializeCommitRequestData(&request);
  350. EXPECT_EQ(metadata_v1.SerializeAsString(),
  351. entity->metadata().SerializeAsString());
  352. EXPECT_TRUE(entity->IsUnsynced());
  353. EXPECT_FALSE(entity->RequiresCommitRequest());
  354. EXPECT_FALSE(entity->RequiresCommitData());
  355. EXPECT_FALSE(entity->CanClearMetadata());
  356. EXPECT_FALSE(entity->HasCommitData());
  357. const EntityData& data = *request.entity;
  358. EXPECT_EQ(kId, data.id);
  359. EXPECT_EQ(kHash, data.client_tag_hash);
  360. EXPECT_EQ("", data.name);
  361. EXPECT_EQ(TimeToProtoTime(ctime_), TimeToProtoTime(data.creation_time));
  362. EXPECT_EQ(entity->metadata().modification_time(),
  363. TimeToProtoTime(data.modification_time));
  364. EXPECT_TRUE(data.is_deleted());
  365. EXPECT_EQ(1, request.sequence_number);
  366. EXPECT_EQ(1, request.base_version);
  367. EXPECT_EQ(entity->metadata().specifics_hash(), request.specifics_hash);
  368. // Ack the deletion.
  369. entity->ReceiveCommitResponse(GenerateAckData(request, kId, 2), false);
  370. EXPECT_TRUE(entity->metadata().is_deleted());
  371. EXPECT_EQ(1, entity->metadata().sequence_number());
  372. EXPECT_EQ(1, entity->metadata().acked_sequence_number());
  373. EXPECT_EQ(2, entity->metadata().server_version());
  374. EXPECT_EQ(metadata_v1.modification_time(),
  375. entity->metadata().modification_time());
  376. EXPECT_TRUE(entity->metadata().specifics_hash().empty());
  377. EXPECT_TRUE(entity->metadata().base_specifics_hash().empty());
  378. EXPECT_FALSE(entity->IsUnsynced());
  379. EXPECT_FALSE(entity->RequiresCommitRequest());
  380. EXPECT_FALSE(entity->RequiresCommitData());
  381. EXPECT_TRUE(entity->CanClearMetadata());
  382. EXPECT_FALSE(entity->HasCommitData());
  383. }
  384. // Test a local deletion followed by an undeletion (creation).
  385. TEST_F(ProcessorEntityTest, LocalUndeletion) {
  386. std::unique_ptr<ProcessorEntity> entity = CreateSynced();
  387. const std::string specifics_hash = entity->metadata().specifics_hash();
  388. entity->RecordLocalDeletion();
  389. ASSERT_TRUE(entity->metadata().is_deleted());
  390. ASSERT_TRUE(entity->IsUnsynced());
  391. ASSERT_EQ(1, entity->metadata().sequence_number());
  392. // Undelete the entity with different specifics.
  393. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue2),
  394. /*trimmed_specifics=*/{});
  395. const std::string specifics_hash_v1 = entity->metadata().specifics_hash();
  396. ASSERT_NE(specifics_hash_v1, specifics_hash);
  397. EXPECT_FALSE(entity->metadata().is_deleted());
  398. EXPECT_EQ(2, entity->metadata().sequence_number());
  399. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  400. EXPECT_EQ(1, entity->metadata().server_version());
  401. EXPECT_TRUE(entity->IsUnsynced());
  402. EXPECT_TRUE(entity->RequiresCommitRequest());
  403. EXPECT_FALSE(entity->RequiresCommitData());
  404. EXPECT_FALSE(entity->CanClearMetadata());
  405. EXPECT_TRUE(entity->HasCommitData());
  406. // Make a commit.
  407. CommitRequestData request;
  408. entity->InitializeCommitRequestData(&request);
  409. EXPECT_EQ(kId, request.entity->id);
  410. EXPECT_FALSE(entity->RequiresCommitRequest());
  411. // Ack the commit.
  412. entity->ReceiveCommitResponse(GenerateAckData(request, kId, 2), false);
  413. EXPECT_EQ(2, entity->metadata().sequence_number());
  414. EXPECT_EQ(2, entity->metadata().acked_sequence_number());
  415. EXPECT_EQ(2, entity->metadata().server_version());
  416. EXPECT_EQ(specifics_hash_v1, entity->metadata().specifics_hash());
  417. EXPECT_EQ("", entity->metadata().base_specifics_hash());
  418. EXPECT_FALSE(entity->IsUnsynced());
  419. EXPECT_FALSE(entity->RequiresCommitRequest());
  420. EXPECT_FALSE(entity->RequiresCommitData());
  421. EXPECT_FALSE(entity->CanClearMetadata());
  422. EXPECT_FALSE(entity->HasCommitData());
  423. }
  424. // Test that hashes and sequence numbers are handled correctly for the "commit
  425. // commit, ack ack" case.
  426. TEST_F(ProcessorEntityTest, LocalChangesInterleaved) {
  427. std::unique_ptr<ProcessorEntity> entity = CreateSynced();
  428. const std::string specifics_hash_v0 = entity->metadata().specifics_hash();
  429. // Make the first change.
  430. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue2),
  431. /*trimmed_specifics=*/{});
  432. const std::string specifics_hash_v1 = entity->metadata().specifics_hash();
  433. EXPECT_EQ(1, entity->metadata().sequence_number());
  434. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  435. EXPECT_NE(specifics_hash_v0, specifics_hash_v1);
  436. EXPECT_EQ(specifics_hash_v0, entity->metadata().base_specifics_hash());
  437. // Request the first commit.
  438. CommitRequestData request_v1;
  439. entity->InitializeCommitRequestData(&request_v1);
  440. // Make the second change.
  441. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue3),
  442. /*trimmed_specifics=*/{});
  443. const std::string specifics_hash_v2 = entity->metadata().specifics_hash();
  444. EXPECT_EQ(2, entity->metadata().sequence_number());
  445. EXPECT_EQ(0, entity->metadata().acked_sequence_number());
  446. EXPECT_NE(specifics_hash_v1, specifics_hash_v2);
  447. EXPECT_EQ(specifics_hash_v0, entity->metadata().base_specifics_hash());
  448. // Request the second commit.
  449. CommitRequestData request_v2;
  450. entity->InitializeCommitRequestData(&request_v2);
  451. EXPECT_TRUE(entity->IsUnsynced());
  452. EXPECT_FALSE(entity->RequiresCommitRequest());
  453. EXPECT_FALSE(entity->RequiresCommitData());
  454. EXPECT_FALSE(entity->CanClearMetadata());
  455. // Ack the first commit.
  456. entity->ReceiveCommitResponse(GenerateAckData(request_v1, kId, 2), false);
  457. EXPECT_EQ(2, entity->metadata().sequence_number());
  458. EXPECT_EQ(1, entity->metadata().acked_sequence_number());
  459. EXPECT_EQ(2, entity->metadata().server_version());
  460. EXPECT_EQ(specifics_hash_v2, entity->metadata().specifics_hash());
  461. EXPECT_EQ(specifics_hash_v1, entity->metadata().base_specifics_hash());
  462. EXPECT_TRUE(entity->IsUnsynced());
  463. EXPECT_FALSE(entity->RequiresCommitRequest());
  464. EXPECT_FALSE(entity->RequiresCommitData());
  465. EXPECT_FALSE(entity->CanClearMetadata());
  466. // Commit data has been moved already to the request.
  467. EXPECT_FALSE(entity->HasCommitData());
  468. // Ack the second commit.
  469. entity->ReceiveCommitResponse(GenerateAckData(request_v2, kId, 3), false);
  470. EXPECT_EQ(2, entity->metadata().sequence_number());
  471. EXPECT_EQ(2, entity->metadata().acked_sequence_number());
  472. EXPECT_EQ(3, entity->metadata().server_version());
  473. EXPECT_EQ(specifics_hash_v2, entity->metadata().specifics_hash());
  474. EXPECT_EQ("", entity->metadata().base_specifics_hash());
  475. EXPECT_FALSE(entity->IsUnsynced());
  476. EXPECT_FALSE(entity->RequiresCommitRequest());
  477. EXPECT_FALSE(entity->RequiresCommitData());
  478. EXPECT_FALSE(entity->CanClearMetadata());
  479. EXPECT_FALSE(entity->HasCommitData());
  480. }
  481. // Tests that updating entity id with commit response while next local change is
  482. // pending correctly updates that change's id and version.
  483. TEST_F(ProcessorEntityTest, NewLocalChangeUpdatedId) {
  484. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  485. // Create new local change. Make sure initial id is empty.
  486. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue1),
  487. /*trimmed_specifics=*/{});
  488. CommitRequestData request;
  489. entity->InitializeCommitRequestData(&request);
  490. EXPECT_TRUE(request.entity->id.empty());
  491. // Before receiving commit response make local modification to the entity.
  492. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue2),
  493. /*trimmed_specifics=*/{});
  494. entity->ReceiveCommitResponse(GenerateAckData(request, kId, 1), false);
  495. // Receiving commit response with valid id should update
  496. // ProcessorEntity. Consecutive commit requests should include updated
  497. // id.
  498. entity->InitializeCommitRequestData(&request);
  499. EXPECT_EQ(kId, request.entity->id);
  500. EXPECT_EQ(1, request.base_version);
  501. }
  502. // Tests that entity restored after restart accepts specifics that don't match
  503. // the ones passed originally to RecordLocalUpdate.
  504. TEST_F(ProcessorEntityTest, RestoredLocalChangeWithUpdatedSpecifics) {
  505. // Create new entity and preserver its metadata.
  506. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  507. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue1),
  508. /*trimmed_specifics=*/{});
  509. sync_pb::EntityMetadata entity_metadata = entity->metadata();
  510. // Restore entity from metadata and emulate bridge passing different specifics
  511. // to SetCommitData.
  512. entity = RestoreFromMetadata(std::move(entity_metadata));
  513. std::unique_ptr<EntityData> entity_data =
  514. GenerateEntityData(kHash, kName, kValue2);
  515. entity->SetCommitData(std::move(entity_data));
  516. // No verification is necessary. SetCommitData shouldn't DCHECK.
  517. }
  518. // Tests the scenario where a local creation conflicts with a remote deletion,
  519. // where usually (and in this test) local wins. In this case, the remote update
  520. // should be ignored but the server IDs should be updated.
  521. TEST_F(ProcessorEntityTest, LocalCreationConflictsWithServerTombstone) {
  522. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  523. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue1),
  524. /*trimmed_specifics=*/{});
  525. ASSERT_TRUE(entity->IsUnsynced());
  526. ASSERT_TRUE(entity->RequiresCommitRequest());
  527. ASSERT_FALSE(entity->RequiresCommitData());
  528. ASSERT_TRUE(entity->HasCommitData());
  529. ASSERT_FALSE(entity->metadata().is_deleted());
  530. ASSERT_TRUE(entity->metadata().server_id().empty());
  531. // Before anything gets committed, we receive a remote tombstone, but local
  532. // would usually win so the remote update is ignored.
  533. UpdateResponseData tombstone =
  534. GenerateTombstone(*entity, kHash, kId, kName, base::Time::Now(), 2);
  535. entity->RecordIgnoredRemoteUpdate(tombstone);
  536. EXPECT_EQ(kId, entity->metadata().server_id());
  537. EXPECT_TRUE(entity->IsUnsynced());
  538. EXPECT_TRUE(entity->RequiresCommitRequest());
  539. EXPECT_FALSE(entity->RequiresCommitData());
  540. EXPECT_TRUE(entity->HasCommitData());
  541. EXPECT_FALSE(entity->metadata().is_deleted());
  542. // Generate a commit request. The server ID should have been reused from the
  543. // otherwise ignored update.
  544. const sync_pb::EntityMetadata metadata_v1 = entity->metadata();
  545. CommitRequestData request;
  546. entity->InitializeCommitRequestData(&request);
  547. EXPECT_EQ(kId, request.entity->id);
  548. }
  549. TEST_F(ProcessorEntityTest, UpdatesSpecificsCacheOnRemoteUpdates) {
  550. base::test::ScopedFeatureList feature_list;
  551. feature_list.InitAndEnableFeature(kCacheBaseEntitySpecificsInMetadata);
  552. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  553. const base::Time mtime = base::Time::Now();
  554. UpdateResponseData update =
  555. GenerateUpdate(*entity, kHash, kId, kName, kValue1, mtime, 10);
  556. sync_pb::EntitySpecifics specifics_for_caching =
  557. GenerateSpecifics(kName, kValue2);
  558. entity->RecordAcceptedRemoteUpdate(update, specifics_for_caching);
  559. EXPECT_EQ(
  560. specifics_for_caching.SerializeAsString(),
  561. entity->metadata().possibly_trimmed_base_specifics().SerializeAsString());
  562. }
  563. TEST_F(ProcessorEntityTest, UpdatesSpecificsCacheOnLocalUpdates) {
  564. base::test::ScopedFeatureList feature_list;
  565. feature_list.InitAndEnableFeature(kCacheBaseEntitySpecificsInMetadata);
  566. std::unique_ptr<ProcessorEntity> entity = CreateNew();
  567. sync_pb::EntitySpecifics specifics_for_caching =
  568. GenerateSpecifics(kName, kValue2);
  569. entity->RecordLocalUpdate(GenerateEntityData(kHash, kName, kValue1),
  570. specifics_for_caching);
  571. EXPECT_EQ(
  572. specifics_for_caching.SerializeAsString(),
  573. entity->metadata().possibly_trimmed_base_specifics().SerializeAsString());
  574. }
  575. } // namespace syncer