client_tag_based_model_type_processor_unittest.cc 116 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953
  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/client_tag_based_model_type_processor.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/run_loop.h"
  13. #include "base/strings/string_number_conversions.h"
  14. #include "base/test/metrics/histogram_tester.h"
  15. #include "base/test/scoped_feature_list.h"
  16. #include "base/test/task_environment.h"
  17. #include "base/threading/platform_thread.h"
  18. #include "components/sync/base/client_tag_hash.h"
  19. #include "components/sync/base/features.h"
  20. #include "components/sync/base/model_type.h"
  21. #include "components/sync/base/sync_mode.h"
  22. #include "components/sync/engine/commit_and_get_updates_types.h"
  23. #include "components/sync/engine/data_type_activation_response.h"
  24. #include "components/sync/model/conflict_resolution.h"
  25. #include "components/sync/model/data_type_activation_request.h"
  26. #include "components/sync/model/type_entities_count.h"
  27. #include "components/sync/protocol/entity_metadata.pb.h"
  28. #include "components/sync/protocol/entity_specifics.pb.h"
  29. #include "components/sync/protocol/model_type_state.pb.h"
  30. #include "components/sync/test/fake_model_type_sync_bridge.h"
  31. #include "components/sync/test/mock_model_type_worker.h"
  32. #include "testing/gtest/include/gtest/gtest.h"
  33. using sync_pb::EntityMetadata;
  34. using sync_pb::EntitySpecifics;
  35. using sync_pb::ModelTypeState;
  36. namespace syncer {
  37. namespace {
  38. const char kDefaultAuthenticatedAccountId[] = "DefaultAccountId";
  39. const char kKey1[] = "key1";
  40. const char kKey2[] = "key2";
  41. const char kKey3[] = "key3";
  42. const char kKey4[] = "key4";
  43. const char kKey5[] = "key5";
  44. const char kValue1[] = "value1";
  45. const char kValue2[] = "value2";
  46. const char kValue3[] = "value3";
  47. const char kCacheGuid[] = "TestCacheGuid";
  48. // Typically used for verification after a delete. The specifics given to the
  49. // worker/processor will not have been initialized and thus empty.
  50. const EntitySpecifics kEmptySpecifics;
  51. ClientTagHash GetHash(ModelType type, const std::string& key) {
  52. return ClientTagHash::FromUnhashed(
  53. type, FakeModelTypeSyncBridge::ClientTagFromKey(key));
  54. }
  55. ClientTagHash GetPrefHash(const std::string& key) {
  56. return GetHash(PREFERENCES, key);
  57. }
  58. EntitySpecifics GeneratePrefSpecifics(const std::string& key,
  59. const std::string& value) {
  60. EntitySpecifics specifics;
  61. specifics.mutable_preference()->set_name(key);
  62. specifics.mutable_preference()->set_value(value);
  63. return specifics;
  64. }
  65. EntitySpecifics GenerateUserEventSpecifics(int64_t event_time_usec,
  66. int64_t navigation_id) {
  67. EntitySpecifics specifics;
  68. specifics.mutable_user_event()->set_event_time_usec(event_time_usec);
  69. specifics.mutable_user_event()->set_navigation_id(navigation_id);
  70. return specifics;
  71. }
  72. std::unique_ptr<EntityData> GenerateEntityData(
  73. ModelType type,
  74. const std::string& key,
  75. const EntitySpecifics& specifics) {
  76. std::unique_ptr<EntityData> entity_data = std::make_unique<EntityData>();
  77. entity_data->client_tag_hash = GetHash(type, key);
  78. entity_data->specifics = specifics;
  79. entity_data->name = key;
  80. return entity_data;
  81. }
  82. std::unique_ptr<EntityData> GeneratePrefEntityData(const std::string& key,
  83. const std::string& value) {
  84. return GenerateEntityData(PREFERENCES, key,
  85. GeneratePrefSpecifics(key, value));
  86. }
  87. EntitySpecifics WritePrefItem(FakeModelTypeSyncBridge* bridge,
  88. const std::string& key,
  89. const std::string& value) {
  90. std::unique_ptr<EntityData> entity_data = GeneratePrefEntityData(key, value);
  91. EntitySpecifics specifics_copy = entity_data->specifics;
  92. bridge->WriteItem(key, std::move(entity_data));
  93. return specifics_copy;
  94. }
  95. const std::string& GetPrefValue(const EntityData& entity_data) {
  96. DCHECK(entity_data.specifics.has_preference());
  97. return entity_data.specifics.preference().value();
  98. }
  99. EntitySpecifics WriteUserEventItem(FakeModelTypeSyncBridge* bridge,
  100. int64_t event_time,
  101. int64_t navigation_id) {
  102. std::string key = base::NumberToString(event_time);
  103. EntitySpecifics specifics =
  104. GenerateUserEventSpecifics(event_time, navigation_id);
  105. bridge->WriteItem(key, GenerateEntityData(USER_EVENTS, key, specifics));
  106. return specifics;
  107. }
  108. void CaptureCommitRequest(CommitRequestDataList* dst,
  109. CommitRequestDataList&& src) {
  110. *dst = std::move(src);
  111. }
  112. void CaptureTypeEntitiesCount(TypeEntitiesCount* dst,
  113. const TypeEntitiesCount& count) {
  114. *dst = count;
  115. }
  116. class TestModelTypeSyncBridge : public FakeModelTypeSyncBridge {
  117. public:
  118. TestModelTypeSyncBridge(ModelType model_type,
  119. bool supports_incremental_updates)
  120. : FakeModelTypeSyncBridge(
  121. model_type,
  122. std::make_unique<ClientTagBasedModelTypeProcessor>(
  123. model_type,
  124. /*dump_stack=*/base::RepeatingClosure())),
  125. supports_incremental_updates_(supports_incremental_updates) {}
  126. TestModelTypeSyncBridge(std::unique_ptr<TestModelTypeSyncBridge> other,
  127. ModelType model_type,
  128. bool supports_clear_all)
  129. : TestModelTypeSyncBridge(model_type, supports_clear_all) {
  130. std::swap(db_, other->db_);
  131. }
  132. ~TestModelTypeSyncBridge() override {
  133. EXPECT_FALSE(synchronous_data_callback_);
  134. EXPECT_FALSE(data_callback_);
  135. }
  136. void OnSyncStarting(
  137. const syncer::DataTypeActivationRequest& request) override {
  138. FakeModelTypeSyncBridge::OnSyncStarting(request);
  139. sync_started_ = true;
  140. }
  141. void ApplyStopSyncChanges(std::unique_ptr<MetadataChangeList>
  142. delete_metadata_change_list) override {
  143. sync_started_ = false;
  144. FakeModelTypeSyncBridge::ApplyStopSyncChanges(
  145. std::move(delete_metadata_change_list));
  146. }
  147. std::string GetStorageKey(const EntityData& entity_data) override {
  148. get_storage_key_call_count_++;
  149. return FakeModelTypeSyncBridge::GetStorageKey(entity_data);
  150. }
  151. sync_pb::EntitySpecifics TrimRemoteSpecificsForCaching(
  152. const sync_pb::EntitySpecifics& entity_specifics) const override {
  153. if (entity_specifics.has_preference()) {
  154. sync_pb::EntitySpecifics trimmed_specifics = entity_specifics;
  155. trimmed_specifics.mutable_preference()->clear_value();
  156. return trimmed_specifics;
  157. }
  158. return FakeModelTypeSyncBridge::TrimRemoteSpecificsForCaching(
  159. entity_specifics);
  160. }
  161. void OnCommitDataLoaded() {
  162. ASSERT_TRUE(data_callback_) << "GetData() wasn't called before";
  163. std::move(data_callback_).Run();
  164. }
  165. base::OnceClosure GetDataCallback() { return std::move(data_callback_); }
  166. void SetInitialSyncDone(bool is_done) {
  167. ModelTypeState model_type_state(db().model_type_state());
  168. model_type_state.set_initial_sync_done(is_done);
  169. model_type_state.set_cache_guid(kCacheGuid);
  170. model_type_state.mutable_progress_marker()->set_data_type_id(
  171. GetSpecificsFieldNumberFromModelType(type()));
  172. model_type_state.set_authenticated_account_id(
  173. kDefaultAuthenticatedAccountId);
  174. db_->set_model_type_state(model_type_state);
  175. }
  176. // Expect a GetData call in the future and return its data immediately.
  177. void ExpectSynchronousDataCallback() { synchronous_data_callback_ = true; }
  178. int merge_call_count() const { return merge_call_count_; }
  179. int apply_call_count() const { return apply_call_count_; }
  180. int get_storage_key_call_count() const { return get_storage_key_call_count_; }
  181. int commit_failures_count() const { return commit_failures_count_; }
  182. bool sync_started() const { return sync_started_; }
  183. // FakeModelTypeSyncBridge overrides.
  184. bool SupportsIncrementalUpdates() const override {
  185. return supports_incremental_updates_;
  186. }
  187. absl::optional<ModelError> MergeSyncData(
  188. std::unique_ptr<MetadataChangeList> metadata_change_list,
  189. EntityChangeList entity_data) override {
  190. merge_call_count_++;
  191. if (!SupportsIncrementalUpdates()) {
  192. // If the bridge does not support incremental updates, it should clear
  193. // local data in MergeSyncData.
  194. db_->ClearAllData();
  195. }
  196. return FakeModelTypeSyncBridge::MergeSyncData(
  197. std::move(metadata_change_list), std::move(entity_data));
  198. }
  199. absl::optional<ModelError> ApplySyncChanges(
  200. std::unique_ptr<MetadataChangeList> metadata_change_list,
  201. EntityChangeList entity_changes) override {
  202. apply_call_count_++;
  203. return FakeModelTypeSyncBridge::ApplySyncChanges(
  204. std::move(metadata_change_list), std::move(entity_changes));
  205. }
  206. void GetData(StorageKeyList keys, DataCallback callback) override {
  207. if (synchronous_data_callback_) {
  208. synchronous_data_callback_ = false;
  209. FakeModelTypeSyncBridge::GetData(keys, std::move(callback));
  210. } else {
  211. FakeModelTypeSyncBridge::GetData(
  212. keys, base::BindOnce(&TestModelTypeSyncBridge::CaptureDataCallback,
  213. base::Unretained(this), std::move(callback)));
  214. }
  215. }
  216. void OnCommitAttemptErrors(
  217. const FailedCommitResponseDataList& error_response_list) override {
  218. if (!on_commit_attempt_errors_callback_.is_null()) {
  219. std::move(on_commit_attempt_errors_callback_).Run(error_response_list);
  220. }
  221. }
  222. CommitAttemptFailedBehavior OnCommitAttemptFailed(
  223. syncer::SyncCommitError commit_error) override {
  224. commit_failures_count_++;
  225. return commit_attempt_failed_behaviour_;
  226. }
  227. void SetOnCommitAttemptErrorsCallback(
  228. base::OnceCallback<void(const FailedCommitResponseDataList&)> callback) {
  229. on_commit_attempt_errors_callback_ = std::move(callback);
  230. }
  231. void EnableRetriesOnCommitFailure() {
  232. commit_attempt_failed_behaviour_ =
  233. CommitAttemptFailedBehavior::kShouldRetryOnNextCycle;
  234. }
  235. private:
  236. void CaptureDataCallback(DataCallback callback,
  237. std::unique_ptr<DataBatch> data) {
  238. EXPECT_FALSE(data_callback_);
  239. data_callback_ = base::BindOnce(std::move(callback), std::move(data));
  240. }
  241. const bool supports_incremental_updates_;
  242. bool sync_started_ = false;
  243. // The number of times MergeSyncData has been called.
  244. int merge_call_count_ = 0;
  245. int apply_call_count_ = 0;
  246. int get_storage_key_call_count_ = 0;
  247. int commit_failures_count_ = 0;
  248. // Stores the data callback between GetData() and OnCommitDataLoaded().
  249. base::OnceClosure data_callback_;
  250. // Whether to return GetData results synchronously. Overrides the default
  251. // callback capture behavior if set to true.
  252. bool synchronous_data_callback_ = false;
  253. CommitAttemptFailedBehavior commit_attempt_failed_behaviour_ =
  254. CommitAttemptFailedBehavior::kDontRetryOnNextCycle;
  255. base::OnceCallback<void(const FailedCommitResponseDataList&)>
  256. on_commit_attempt_errors_callback_;
  257. };
  258. } // namespace
  259. // Tests the various functionality of ClientTagBasedModelTypeProcessor.
  260. //
  261. // The processor sits between the bridge (implemented by this test class) and
  262. // the worker, which is represented by a MockModelTypeWorker. This test suite
  263. // exercises the initialization flows (whether initial sync is done, performing
  264. // the initial merge, etc) as well as normal functionality:
  265. //
  266. // - Initialization before the initial sync and merge correctly performs a merge
  267. // and initializes the metadata in storage.
  268. // - Initialization after the initial sync correctly loads metadata and queues
  269. // any pending commits.
  270. // - Put and Delete calls from the bridge result in the correct metadata in
  271. // storage and the correct commit requests on the worker side.
  272. // - Updates and commit responses from the worker correctly affect data and
  273. // metadata in storage on the bridge side.
  274. class ClientTagBasedModelTypeProcessorTest : public ::testing::Test {
  275. public:
  276. ClientTagBasedModelTypeProcessorTest() = default;
  277. ~ClientTagBasedModelTypeProcessorTest() override { CheckPostConditions(); }
  278. void SetUp() override {
  279. bridge_ = std::make_unique<TestModelTypeSyncBridge>(
  280. GetModelType(), SupportsIncrementalUpdates());
  281. histogram_tester_ = std::make_unique<base::HistogramTester>();
  282. }
  283. void InitializeToMetadataLoaded(bool initial_sync_done = true) {
  284. bridge()->SetInitialSyncDone(initial_sync_done);
  285. ModelReadyToSync();
  286. }
  287. // Initialize to a "ready-to-commit" state.
  288. void InitializeToReadyState() {
  289. InitializeToMetadataLoaded();
  290. OnSyncStarting();
  291. }
  292. void ModelReadyToSync() {
  293. type_processor()->ModelReadyToSync(db()->CreateMetadataBatch());
  294. WaitForStartCallbackIfNeeded();
  295. }
  296. void OnCommitDataLoaded() { bridge()->OnCommitDataLoaded(); }
  297. void OnSyncStarting(const std::string& authenticated_account_id =
  298. kDefaultAuthenticatedAccountId,
  299. const std::string& cache_guid = kCacheGuid,
  300. SyncMode sync_mode = SyncMode::kFull) {
  301. DataTypeActivationRequest request;
  302. request.error_handler = base::BindRepeating(
  303. &ClientTagBasedModelTypeProcessorTest::ErrorReceived,
  304. base::Unretained(this));
  305. request.cache_guid = cache_guid;
  306. request.authenticated_account_id = CoreAccountId(authenticated_account_id);
  307. request.sync_mode = sync_mode;
  308. request.configuration_start_time = base::Time::Now();
  309. // |run_loop_| may exist here if OnSyncStarting is called without resetting
  310. // state. But it is safe to remove it.
  311. ASSERT_TRUE(!run_loop_ || !run_loop_->running());
  312. run_loop_ = std::make_unique<base::RunLoop>();
  313. type_processor()->OnSyncStarting(
  314. request,
  315. base::BindOnce(&ClientTagBasedModelTypeProcessorTest::OnReadyToConnect,
  316. base::Unretained(this)));
  317. WaitForStartCallbackIfNeeded();
  318. }
  319. void DisconnectSync() {
  320. type_processor()->DisconnectSync();
  321. worker_ = nullptr;
  322. }
  323. // Writes data for |key| and simulates a commit response for it.
  324. EntitySpecifics WriteItemAndAck(const std::string& key,
  325. const std::string& value) {
  326. EntitySpecifics specifics = WritePrefItem(bridge(), key, value);
  327. base::RunLoop().RunUntilIdle();
  328. worker()->VerifyPendingCommits({{GetPrefHash(key)}});
  329. worker()->AckOnePendingCommit();
  330. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  331. return specifics;
  332. }
  333. void WriteItemAndAck(const std::string& key,
  334. std::unique_ptr<EntityData> entity_data) {
  335. bridge()->WriteItem(key, std::move(entity_data));
  336. worker()->VerifyPendingCommits({{GetPrefHash(key)}});
  337. worker()->AckOnePendingCommit();
  338. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  339. return;
  340. }
  341. const ProcessorEntity* GetEntityForStorageKey(
  342. const std::string& storage_key) {
  343. return type_processor()->entity_tracker_->GetEntityForStorageKey(
  344. storage_key);
  345. }
  346. void ResetState(bool keep_db) {
  347. bridge_ = keep_db ? std::make_unique<TestModelTypeSyncBridge>(
  348. std::move(bridge_), GetModelType(),
  349. SupportsIncrementalUpdates())
  350. : std::make_unique<TestModelTypeSyncBridge>(
  351. GetModelType(), SupportsIncrementalUpdates());
  352. worker_ = nullptr;
  353. run_loop_.reset();
  354. CheckPostConditions();
  355. histogram_tester_ = std::make_unique<base::HistogramTester>();
  356. }
  357. virtual ModelType GetModelType() { return PREFERENCES; }
  358. virtual bool SupportsIncrementalUpdates() { return true; }
  359. // Wipes existing DB and simulates a pending update of a server-known item.
  360. EntitySpecifics ResetStateWriteItem(const std::string& name,
  361. const std::string& value) {
  362. ResetState(false);
  363. InitializeToReadyState();
  364. EXPECT_EQ(0U, ProcessorEntityCount());
  365. WriteItemAndAck(name, "acked-value");
  366. EntitySpecifics specifics = WritePrefItem(bridge(), name, value);
  367. EXPECT_EQ(1U, ProcessorEntityCount());
  368. ResetState(true);
  369. return specifics;
  370. }
  371. // Wipes existing DB and simulates a pending deletion of a server-known item.
  372. void ResetStateDeleteItem(const std::string& name, const std::string& value) {
  373. ResetState(false);
  374. InitializeToReadyState();
  375. EXPECT_EQ(0U, ProcessorEntityCount());
  376. WriteItemAndAck(name, value);
  377. EXPECT_EQ(1U, ProcessorEntityCount());
  378. bridge()->DeleteItem(name);
  379. EXPECT_EQ(1U, ProcessorEntityCount());
  380. ResetState(true);
  381. }
  382. // Return the number of entities the processor has metadata for.
  383. size_t ProcessorEntityCount() const {
  384. if (type_processor()->entity_tracker_)
  385. return type_processor()->entity_tracker_->size();
  386. return 0;
  387. }
  388. // Expect to receive an error from the processor.
  389. void ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite error_site) {
  390. EXPECT_FALSE(expect_error_);
  391. expect_error_ = error_site;
  392. }
  393. TestModelTypeSyncBridge* bridge() const { return bridge_.get(); }
  394. FakeModelTypeSyncBridge::Store* db() const { return bridge()->mutable_db(); }
  395. MockModelTypeWorker* worker() const { return worker_; }
  396. ClientTagBasedModelTypeProcessor* type_processor() const {
  397. return static_cast<ClientTagBasedModelTypeProcessor*>(
  398. bridge()->change_processor());
  399. }
  400. protected:
  401. void CheckPostConditions() { EXPECT_FALSE(expect_error_); }
  402. void OnReadyToConnect(std::unique_ptr<DataTypeActivationResponse> context) {
  403. model_type_state_ = context->model_type_state;
  404. std::unique_ptr<MockModelTypeWorker> worker =
  405. std::make_unique<MockModelTypeWorker>(model_type_state_,
  406. type_processor());
  407. // Keep an unsafe pointer to the commit queue the processor will use.
  408. worker_ = worker.get();
  409. // The context contains a proxy to the processor, but this call is
  410. // side-stepping that completely and connecting directly to the real
  411. // processor, since these tests are single-threaded and don't need proxies.
  412. type_processor()->ConnectSync(std::move(worker));
  413. ASSERT_TRUE(run_loop_);
  414. run_loop_->Quit();
  415. }
  416. void ErrorReceived(const ModelError& error) {
  417. EXPECT_TRUE(expect_error_);
  418. histogram_tester_->ExpectBucketCount("Sync.ModelTypeErrorSite.PREFERENCE",
  419. *expect_error_, /*count=*/1);
  420. expect_error_ = absl::nullopt;
  421. // Do not expect for a start callback anymore.
  422. if (run_loop_) {
  423. run_loop_->Quit();
  424. }
  425. }
  426. sync_pb::ModelTypeState model_type_state() { return model_type_state_; }
  427. void WaitForStartCallbackIfNeeded() {
  428. if (!type_processor()->IsModelReadyToSyncForTest() ||
  429. !bridge()->sync_started()) {
  430. return;
  431. }
  432. ASSERT_TRUE(run_loop_);
  433. run_loop_->Run();
  434. }
  435. private:
  436. std::unique_ptr<TestModelTypeSyncBridge> bridge_;
  437. sync_pb::ModelTypeState model_type_state_;
  438. // This sets SequencedTaskRunnerHandle on the current thread, which the type
  439. // processor will pick up as the sync task runner.
  440. base::test::SingleThreadTaskEnvironment task_environment_;
  441. // This run loop is used to wait for OnReadyToConnect is called.
  442. std::unique_ptr<base::RunLoop> run_loop_;
  443. // The current mock queue, which is owned by |type_processor()|.
  444. raw_ptr<MockModelTypeWorker> worker_;
  445. // Whether to expect an error from the processor (and from which site).
  446. absl::optional<ClientTagBasedModelTypeProcessor::ErrorSite> expect_error_;
  447. std::unique_ptr<base::HistogramTester> histogram_tester_;
  448. };
  449. TEST_F(ClientTagBasedModelTypeProcessorTest,
  450. ShouldExposeNewlyTrackedAccountId) {
  451. ModelReadyToSync();
  452. ASSERT_EQ("", type_processor()->TrackedAccountId());
  453. OnSyncStarting();
  454. worker()->UpdateFromServer();
  455. EXPECT_EQ(kDefaultAuthenticatedAccountId,
  456. type_processor()->TrackedAccountId());
  457. }
  458. TEST_F(ClientTagBasedModelTypeProcessorTest,
  459. ShouldExposePreviouslyTrackedAccountId) {
  460. std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch();
  461. sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState());
  462. model_type_state.set_initial_sync_done(true);
  463. model_type_state.set_cache_guid(kCacheGuid);
  464. model_type_state.set_authenticated_account_id("PersistedAccountId");
  465. model_type_state.mutable_progress_marker()->set_data_type_id(
  466. GetSpecificsFieldNumberFromModelType(GetModelType()));
  467. metadata_batch->SetModelTypeState(model_type_state);
  468. type_processor()->ModelReadyToSync(std::move(metadata_batch));
  469. // Even prior to starting sync, the account ID should already be tracked.
  470. EXPECT_EQ("PersistedAccountId", type_processor()->TrackedAccountId());
  471. // If sync gets started, the account should still be tracked.
  472. OnSyncStarting("PersistedAccountId");
  473. EXPECT_EQ("PersistedAccountId", type_processor()->TrackedAccountId());
  474. }
  475. TEST_F(ClientTagBasedModelTypeProcessorTest,
  476. ShouldExposeNewlyTrackedAccountIdIfChanged) {
  477. std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch();
  478. sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState());
  479. model_type_state.set_initial_sync_done(true);
  480. model_type_state.set_cache_guid(kCacheGuid);
  481. model_type_state.set_authenticated_account_id("PersistedAccountId");
  482. model_type_state.mutable_progress_marker()->set_data_type_id(
  483. GetSpecificsFieldNumberFromModelType(GetModelType()));
  484. metadata_batch->SetModelTypeState(model_type_state);
  485. type_processor()->ModelReadyToSync(std::move(metadata_batch));
  486. // Even prior to starting sync, the account ID should already be tracked.
  487. ASSERT_EQ("PersistedAccountId", type_processor()->TrackedAccountId());
  488. // If sync gets started, the new account should be tracked.
  489. OnSyncStarting("NewAccountId");
  490. EXPECT_TRUE(type_processor()->IsTrackingMetadata());
  491. EXPECT_EQ("NewAccountId", type_processor()->TrackedAccountId());
  492. }
  493. TEST_F(ClientTagBasedModelTypeProcessorTest,
  494. ShouldExposeNewlyTrackedCacheGuid) {
  495. ModelReadyToSync();
  496. ASSERT_EQ("", type_processor()->TrackedCacheGuid());
  497. OnSyncStarting();
  498. worker()->UpdateFromServer();
  499. EXPECT_EQ(kCacheGuid, type_processor()->TrackedCacheGuid());
  500. }
  501. TEST_F(ClientTagBasedModelTypeProcessorTest,
  502. ShouldExposePreviouslyTrackedCacheGuid) {
  503. std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch();
  504. sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState());
  505. model_type_state.set_initial_sync_done(true);
  506. model_type_state.set_cache_guid("PersistedCacheGuid");
  507. model_type_state.set_authenticated_account_id(kDefaultAuthenticatedAccountId);
  508. model_type_state.mutable_progress_marker()->set_data_type_id(
  509. GetSpecificsFieldNumberFromModelType(GetModelType()));
  510. metadata_batch->SetModelTypeState(model_type_state);
  511. type_processor()->ModelReadyToSync(std::move(metadata_batch));
  512. // Even prior to starting sync, the cache guid should be set.
  513. EXPECT_EQ("PersistedCacheGuid", type_processor()->TrackedCacheGuid());
  514. // If sync gets started, the cache guid should still be set.
  515. OnSyncStarting(kDefaultAuthenticatedAccountId, "PersistedCacheGuid");
  516. EXPECT_EQ("PersistedCacheGuid", type_processor()->TrackedCacheGuid());
  517. }
  518. // Test that an initial sync handles local and remote items properly.
  519. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldMergeLocalAndRemoteChanges) {
  520. base::test::ScopedFeatureList feature_list;
  521. feature_list.InitAndEnableFeature(kCacheBaseEntitySpecificsInMetadata);
  522. ModelReadyToSync();
  523. OnSyncStarting();
  524. // Local write before initial sync.
  525. WritePrefItem(bridge(), kKey1, kValue1);
  526. // Has data, but no metadata, entity in the processor, or commit request.
  527. EXPECT_EQ(1U, db()->data_count());
  528. EXPECT_EQ(0U, db()->metadata_count());
  529. EXPECT_EQ(0U, ProcessorEntityCount());
  530. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  531. EXPECT_EQ(0, bridge()->merge_call_count());
  532. // Initial sync with one server item.
  533. base::HistogramTester histogram_tester;
  534. worker()->UpdateFromServer(GetPrefHash(kKey2),
  535. GeneratePrefSpecifics(kKey2, kValue2));
  536. EXPECT_EQ(1, bridge()->merge_call_count());
  537. histogram_tester.ExpectUniqueSample(
  538. "Sync.ModelTypeInitialUpdateReceived",
  539. /*sample=*/syncer::ModelTypeHistogramValue(GetModelType()),
  540. /*expected_count=*/1);
  541. // Now have data and metadata for both items, as well as a commit request for
  542. // the local item.
  543. EXPECT_EQ(2U, db()->data_count());
  544. EXPECT_EQ(2U, db()->metadata_count());
  545. EXPECT_EQ(2U, ProcessorEntityCount());
  546. EXPECT_EQ(1, db()->GetMetadata(kKey1).sequence_number());
  547. EXPECT_EQ(0, db()->GetMetadata(kKey2).sequence_number());
  548. EXPECT_TRUE(db()->GetMetadata(kKey1).has_possibly_trimmed_base_specifics());
  549. EXPECT_TRUE(db()->GetMetadata(kKey2).has_possibly_trimmed_base_specifics());
  550. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  551. }
  552. TEST_F(ClientTagBasedModelTypeProcessorTest,
  553. ShouldExposePossiblyTrimmedRemoteSpecifics) {
  554. base::test::ScopedFeatureList feature_list;
  555. feature_list.InitAndEnableFeature(kCacheBaseEntitySpecificsInMetadata);
  556. ModelReadyToSync();
  557. OnSyncStarting();
  558. sync_pb::EntitySpecifics specififcs = GeneratePrefSpecifics(kKey1, kValue1);
  559. *specififcs.mutable_preference()->mutable_unknown_fields() = kValue2;
  560. worker()->UpdateFromServer(GetPrefHash(kKey1), specififcs);
  561. sync_pb::PreferenceSpecifics cached_preference =
  562. type_processor()->GetPossiblyTrimmedRemoteSpecifics(kKey1).preference();
  563. // Below verifies that
  564. // TestModelTypeSyncBridge::TrimRemoteSpecificsForCaching() is honored.
  565. // Preserved fields.
  566. EXPECT_EQ(cached_preference.name(), kKey1);
  567. EXPECT_EQ(cached_preference.unknown_fields(), kValue2);
  568. // Trimmed field.
  569. EXPECT_FALSE(cached_preference.has_value());
  570. }
  571. // Test that an initial sync filters out tombstones in the processor.
  572. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldFilterOutInitialTombstones) {
  573. ModelReadyToSync();
  574. OnSyncStarting();
  575. EXPECT_EQ(0, bridge()->merge_call_count());
  576. // Initial sync with a tombstone. The fake bridge checks that it doesn't get
  577. // any tombstones in its MergeSyncData function.
  578. worker()->TombstoneFromServer(GetPrefHash(kKey1));
  579. EXPECT_EQ(1, bridge()->merge_call_count());
  580. // Should still have no data, metadata, or commit requests.
  581. EXPECT_EQ(0U, db()->data_count());
  582. EXPECT_EQ(0U, db()->metadata_count());
  583. EXPECT_EQ(0U, ProcessorEntityCount());
  584. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  585. }
  586. // Test that an initial sync filters out updates for root nodes in the
  587. // processor.
  588. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldFilterOutInitialRootNodes) {
  589. ModelReadyToSync();
  590. OnSyncStarting();
  591. UpdateResponseDataList update;
  592. update.push_back(worker()->GenerateTypeRootUpdateData(ModelType::SESSIONS));
  593. worker()->UpdateFromServer(std::move(update));
  594. // Root node update should be filtered out.
  595. EXPECT_EQ(0U, ProcessorEntityCount());
  596. }
  597. // Test that subsequent starts don't call MergeSyncData.
  598. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldApplyIncrementalUpdates) {
  599. // This sets initial_sync_done to true.
  600. InitializeToMetadataLoaded();
  601. // Write an item before sync connects.
  602. WritePrefItem(bridge(), kKey1, kValue1);
  603. EXPECT_EQ(1U, db()->data_count());
  604. EXPECT_EQ(1U, db()->metadata_count());
  605. // Check that data coming from sync is treated as a normal GetUpdates.
  606. OnSyncStarting();
  607. base::HistogramTester histogram_tester;
  608. worker()->UpdateFromServer(GetPrefHash(kKey2),
  609. GeneratePrefSpecifics(kKey2, kValue2));
  610. EXPECT_EQ(0, bridge()->merge_call_count());
  611. EXPECT_EQ(1, bridge()->apply_call_count());
  612. EXPECT_EQ(2U, db()->data_count());
  613. EXPECT_EQ(2U, db()->metadata_count());
  614. histogram_tester.ExpectUniqueSample(
  615. "Sync.ModelTypeIncrementalUpdateReceived",
  616. /*sample=*/syncer::ModelTypeHistogramValue(GetModelType()),
  617. /*expected_count=*/1);
  618. }
  619. // Test that an error during the merge is propagated to the error handler.
  620. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldReportErrorDuringMerge) {
  621. ModelReadyToSync();
  622. OnSyncStarting();
  623. bridge()->ErrorOnNextCall();
  624. ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite::kApplyFullUpdates);
  625. worker()->UpdateFromServer();
  626. }
  627. // Test that errors before it's called are passed to |start_callback| correctly.
  628. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldDeferErrorsBeforeStart) {
  629. type_processor()->ReportError({FROM_HERE, "boom"});
  630. ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite::kBridgeInitiated);
  631. OnSyncStarting();
  632. // Test OnSyncStarting happening first.
  633. ResetState(false);
  634. OnSyncStarting();
  635. ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite::kBridgeInitiated);
  636. type_processor()->ReportError({FROM_HERE, "boom"});
  637. // Test an error loading pending data.
  638. ResetStateWriteItem(kKey1, kValue1);
  639. bridge()->ErrorOnNextCall();
  640. InitializeToMetadataLoaded();
  641. ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite::kBridgeInitiated);
  642. OnSyncStarting();
  643. // Test an error prior to metadata load.
  644. ResetState(false);
  645. type_processor()->ReportError({FROM_HERE, "boom"});
  646. ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite::kBridgeInitiated);
  647. OnSyncStarting();
  648. ModelReadyToSync();
  649. // Test an error prior to pending data load.
  650. ResetStateWriteItem(kKey1, kValue1);
  651. InitializeToMetadataLoaded();
  652. type_processor()->ReportError({FROM_HERE, "boom"});
  653. ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite::kBridgeInitiated);
  654. OnSyncStarting();
  655. }
  656. // This test covers race conditions during loading pending data. All cases
  657. // start with no processor and one acked (committed to the server) item with a
  658. // pending commit. There are three different events that occur once metadata
  659. // is loaded:
  660. //
  661. // - Sync gets connected once sync in ready.
  662. // - Commit data is loaded. This happens only after Sync gets connected.
  663. // - Optionally, a put or delete happens to the item.
  664. //
  665. // This results in 1 + 6 = 7 orderings of the events.
  666. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldLoadDataForPendingCommit) {
  667. // Connect, data.
  668. EntitySpecifics specifics2 = ResetStateWriteItem(kKey1, kValue1);
  669. InitializeToMetadataLoaded();
  670. OnSyncStarting();
  671. OnCommitDataLoaded();
  672. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  673. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics2});
  674. // Connect, data, put.
  675. EntitySpecifics specifics6 = ResetStateWriteItem(kKey1, kValue1);
  676. InitializeToMetadataLoaded();
  677. OnSyncStarting();
  678. OnCommitDataLoaded();
  679. EntitySpecifics specifics7 = WritePrefItem(bridge(), kKey1, kValue2);
  680. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  681. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics6});
  682. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1)}, {specifics7});
  683. // Connect, put, data.
  684. EntitySpecifics specifics100 = ResetStateWriteItem(kKey1, kValue1);
  685. InitializeToMetadataLoaded();
  686. OnSyncStarting();
  687. EntitySpecifics specifics8 = WritePrefItem(bridge(), kKey1, kValue2);
  688. OnCommitDataLoaded();
  689. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  690. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics8});
  691. // GetData was launched as a result of GetLocalChanges call(). Since all data
  692. // are in memory, the 2nd pending commit should be empty.
  693. worker()->VerifyNthPendingCommit(1, {}, {});
  694. // Put, connect, data.
  695. ResetStateWriteItem(kKey1, kValue1);
  696. InitializeToMetadataLoaded();
  697. EntitySpecifics specifics10 = WritePrefItem(bridge(), kKey1, kValue2);
  698. OnSyncStarting();
  699. EXPECT_FALSE(bridge()->GetDataCallback());
  700. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  701. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics10});
  702. // Connect, data, delete.
  703. EntitySpecifics specifics12 = ResetStateWriteItem(kKey1, kValue1);
  704. InitializeToMetadataLoaded();
  705. OnSyncStarting();
  706. OnCommitDataLoaded();
  707. bridge()->DeleteItem(kKey1);
  708. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  709. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics12});
  710. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1)}, {kEmptySpecifics});
  711. // Connect, delete, data.
  712. ResetStateWriteItem(kKey1, kValue1);
  713. InitializeToMetadataLoaded();
  714. OnSyncStarting();
  715. bridge()->DeleteItem(kKey1);
  716. OnCommitDataLoaded();
  717. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  718. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {kEmptySpecifics});
  719. // GetData was launched as a result of GetLocalChanges call(). Since all data
  720. // are in memory, the 2nd pending commit should be empty.
  721. worker()->VerifyNthPendingCommit(1, {}, {});
  722. // Delete, connect, data.
  723. ResetStateWriteItem(kKey1, kValue1);
  724. InitializeToMetadataLoaded();
  725. bridge()->DeleteItem(kKey1);
  726. OnSyncStarting();
  727. EXPECT_FALSE(bridge()->GetDataCallback());
  728. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  729. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {kEmptySpecifics});
  730. }
  731. // Tests cases where pending data loads synchronously.
  732. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldHandleSynchronousDataLoad) {
  733. // Model, sync.
  734. EntitySpecifics specifics1 = ResetStateWriteItem(kKey1, kValue1);
  735. bridge()->ExpectSynchronousDataCallback();
  736. InitializeToMetadataLoaded();
  737. OnSyncStarting();
  738. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  739. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics1});
  740. // Sync, model.
  741. EntitySpecifics specifics2 = ResetStateWriteItem(kKey1, kValue1);
  742. OnSyncStarting();
  743. bridge()->ExpectSynchronousDataCallback();
  744. InitializeToMetadataLoaded();
  745. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  746. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics2});
  747. }
  748. // This test covers race conditions during loading a pending delete. All cases
  749. // start with no processor and one item with a pending delete. There are two
  750. // different events that can occur in any order once metadata is loaded, since
  751. // for a deletion there is no data to load:
  752. //
  753. // - Sync gets connected.
  754. // - Optionally, a put or delete happens to the item (repeated deletes should be
  755. // handled properly).
  756. //
  757. // This results in 1 + 4 = 5 orderings of the events.
  758. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldLoadPendingDelete) {
  759. // Connect.
  760. ResetStateDeleteItem(kKey1, kValue1);
  761. InitializeToMetadataLoaded();
  762. OnSyncStarting();
  763. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  764. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {kEmptySpecifics});
  765. // Connect, put.
  766. ResetStateDeleteItem(kKey1, kValue1);
  767. InitializeToMetadataLoaded();
  768. OnSyncStarting();
  769. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  770. EntitySpecifics specifics1 = WritePrefItem(bridge(), kKey1, kValue2);
  771. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  772. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {kEmptySpecifics});
  773. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1)}, {specifics1});
  774. // Put, connect.
  775. ResetStateDeleteItem(kKey1, kValue1);
  776. InitializeToMetadataLoaded();
  777. EntitySpecifics specifics2 = WritePrefItem(bridge(), kKey1, kValue2);
  778. OnSyncStarting();
  779. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  780. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics2});
  781. // Connect, delete.
  782. ResetStateDeleteItem(kKey1, kValue1);
  783. InitializeToMetadataLoaded();
  784. OnSyncStarting();
  785. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  786. bridge()->DeleteItem(kKey1);
  787. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  788. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {kEmptySpecifics});
  789. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1)}, {kEmptySpecifics});
  790. // Delete, connect.
  791. ResetStateDeleteItem(kKey1, kValue1);
  792. InitializeToMetadataLoaded();
  793. bridge()->DeleteItem(kKey1);
  794. OnSyncStarting();
  795. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  796. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {kEmptySpecifics});
  797. }
  798. // Test that loading a committed item does not queue another commit.
  799. TEST_F(ClientTagBasedModelTypeProcessorTest,
  800. ShouldNotQueueAnotherCommitIfAlreadyCommitted) {
  801. InitializeToReadyState();
  802. WriteItemAndAck(kKey1, kValue1);
  803. ResetState(true);
  804. // Test that a new processor loads the metadata without committing.
  805. InitializeToReadyState();
  806. EXPECT_EQ(1U, ProcessorEntityCount());
  807. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  808. }
  809. // Creates a new item locally.
  810. // Thoroughly tests the data generated by a local item creation.
  811. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldCommitLocalCreation) {
  812. base::test::ScopedFeatureList feature_list;
  813. feature_list.InitAndEnableFeature(kCacheBaseEntitySpecificsInMetadata);
  814. base::HistogramTester histogram_tester;
  815. InitializeToReadyState();
  816. ASSERT_EQ(0U, worker()->GetNumPendingCommits());
  817. ASSERT_FALSE(type_processor()->IsEntityUnsynced(kKey1));
  818. WritePrefItem(bridge(), kKey1, kValue1);
  819. EXPECT_TRUE(type_processor()->IsEntityUnsynced(kKey1));
  820. EXPECT_FALSE(type_processor()->GetEntityCreationTime(kKey1).is_null());
  821. EXPECT_EQ(type_processor()->GetEntityCreationTime(kKey1),
  822. type_processor()->GetEntityModificationTime(kKey1));
  823. // Verify the commit request this operation has triggered.
  824. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  825. const CommitRequestData* tag1_request_data =
  826. worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1));
  827. ASSERT_TRUE(tag1_request_data);
  828. const EntityData& tag1_data = *tag1_request_data->entity;
  829. EXPECT_EQ(kUncommittedVersion, tag1_request_data->base_version);
  830. EXPECT_TRUE(tag1_data.id.empty());
  831. EXPECT_FALSE(tag1_data.creation_time.is_null());
  832. EXPECT_FALSE(tag1_data.modification_time.is_null());
  833. EXPECT_EQ(kKey1, tag1_data.name);
  834. EXPECT_FALSE(tag1_data.is_deleted());
  835. EXPECT_EQ(kKey1, tag1_data.specifics.preference().name());
  836. EXPECT_EQ(kValue1, tag1_data.specifics.preference().value());
  837. EXPECT_EQ(1U, db()->metadata_count());
  838. const EntityMetadata metadata = db()->GetMetadata(kKey1);
  839. EXPECT_TRUE(metadata.has_client_tag_hash());
  840. EXPECT_FALSE(metadata.has_server_id());
  841. EXPECT_FALSE(metadata.is_deleted());
  842. EXPECT_EQ(1, metadata.sequence_number());
  843. EXPECT_EQ(0, metadata.acked_sequence_number());
  844. EXPECT_EQ(kUncommittedVersion, metadata.server_version());
  845. EXPECT_TRUE(metadata.has_creation_time());
  846. EXPECT_TRUE(metadata.has_modification_time());
  847. EXPECT_TRUE(metadata.has_specifics_hash());
  848. EXPECT_TRUE(metadata.has_possibly_trimmed_base_specifics());
  849. worker()->AckOnePendingCommit();
  850. EXPECT_FALSE(type_processor()->IsEntityUnsynced(kKey1));
  851. EXPECT_EQ(1U, db()->metadata_count());
  852. const EntityMetadata acked_metadata = db()->GetMetadata(kKey1);
  853. EXPECT_TRUE(acked_metadata.has_server_id());
  854. EXPECT_EQ(1, acked_metadata.sequence_number());
  855. EXPECT_EQ(1, acked_metadata.acked_sequence_number());
  856. EXPECT_EQ(1, acked_metadata.server_version());
  857. histogram_tester.ExpectBucketCount(
  858. "Sync.ModelTypeOrphanMetadata.Put",
  859. /*bucket=*/ModelTypeHistogramValue(GetModelType()), /*count=*/0);
  860. }
  861. // Creates a new item locally while another item exists for the same client tag
  862. // hash.
  863. TEST_F(ClientTagBasedModelTypeProcessorTest,
  864. CommitShouldOverwriteExistingItem) {
  865. base::test::ScopedFeatureList feature_list;
  866. feature_list.InitAndEnableFeature(kCacheBaseEntitySpecificsInMetadata);
  867. base::HistogramTester histogram_tester;
  868. // Provide custom client tags for this test.
  869. bridge()->SetSupportsGetClientTag(false);
  870. const syncer::ClientTagHash kClientTagHash =
  871. ClientTagHash::FromUnhashed(PREFERENCES, "tag");
  872. InitializeToReadyState();
  873. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  874. std::unique_ptr<EntityData> entity_data1 =
  875. GeneratePrefEntityData(kKey1, kValue1);
  876. // Use a custom client tag hash - independent of the storage key.
  877. entity_data1->client_tag_hash = kClientTagHash;
  878. bridge()->WriteItem(kKey1, std::move(entity_data1));
  879. EXPECT_EQ(1U, db()->metadata_count());
  880. worker()->VerifyPendingCommits({{kClientTagHash}});
  881. std::unique_ptr<EntityData> entity_data2 =
  882. GeneratePrefEntityData(kKey2, kValue2);
  883. // Use the same custom client tag hash as for entity 1.
  884. entity_data2->client_tag_hash = kClientTagHash;
  885. bridge()->WriteItem(kKey2, std::move(entity_data2));
  886. EXPECT_EQ(1U, db()->metadata_count());
  887. EXPECT_TRUE(db()->GetMetadata(kKey2).has_possibly_trimmed_base_specifics());
  888. histogram_tester.ExpectBucketCount(
  889. "Sync.ModelTypeOrphanMetadata.Put",
  890. /*bucket=*/ModelTypeHistogramValue(GetModelType()),
  891. /*count=*/1);
  892. }
  893. // Test that an error applying metadata changes from a commit response is
  894. // propagated to the error handler.
  895. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldReportErrorApplyingAck) {
  896. InitializeToReadyState();
  897. WritePrefItem(bridge(), kKey1, kValue1);
  898. bridge()->ErrorOnNextCall();
  899. ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite::
  900. kApplyUpdatesOnCommitResponse);
  901. worker()->AckOnePendingCommit();
  902. }
  903. // The purpose of this test case is to test setting |client_tag_hash| and |id|
  904. // on the EntityData object as we pass it into the Put method of the processor.
  905. TEST_F(ClientTagBasedModelTypeProcessorTest,
  906. ShouldOverrideFieldsForLocalUpdate) {
  907. const std::string kId1 = "cid1";
  908. const std::string kId2 = "cid2";
  909. InitializeToReadyState();
  910. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  911. std::unique_ptr<EntityData> entity_data = std::make_unique<EntityData>();
  912. entity_data->specifics.mutable_preference()->set_name(kKey1);
  913. entity_data->specifics.mutable_preference()->set_value(kValue1);
  914. entity_data->name = kKey1;
  915. entity_data->client_tag_hash = GetPrefHash(kKey1);
  916. entity_data->id = kId1;
  917. bridge()->WriteItem(kKey1, std::move(entity_data));
  918. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  919. ASSERT_FALSE(worker()->HasPendingCommitForHash(GetPrefHash(kKey3)));
  920. ASSERT_TRUE(worker()->HasPendingCommitForHash(GetPrefHash(kKey1)));
  921. EXPECT_EQ(1U, db()->metadata_count());
  922. ASSERT_TRUE(worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1)));
  923. const EntityData& out_entity1 =
  924. *worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1))->entity;
  925. const EntityMetadata metadata_v1 = db()->GetMetadata(kKey1);
  926. EXPECT_EQ(kId1, out_entity1.id);
  927. EXPECT_NE(GetPrefHash(kKey3), out_entity1.client_tag_hash);
  928. EXPECT_EQ(kValue1, out_entity1.specifics.preference().value());
  929. EXPECT_EQ(kId1, metadata_v1.server_id());
  930. EXPECT_EQ(metadata_v1.client_tag_hash(), out_entity1.client_tag_hash.value());
  931. entity_data = std::make_unique<EntityData>();
  932. // This is a sketchy move here, changing the name will change the generated
  933. // storage key and client tag values.
  934. entity_data->specifics.mutable_preference()->set_name(kKey2);
  935. entity_data->specifics.mutable_preference()->set_value(kValue2);
  936. entity_data->name = kKey2;
  937. entity_data->client_tag_hash = GetPrefHash(kKey3);
  938. // Make sure ID isn't overwritten either.
  939. entity_data->id = kId2;
  940. bridge()->WriteItem(kKey1, std::move(entity_data));
  941. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  942. ASSERT_FALSE(worker()->HasPendingCommitForHash(GetPrefHash(kKey3)));
  943. ASSERT_TRUE(worker()->HasPendingCommitForHash(GetPrefHash(kKey1)));
  944. EXPECT_EQ(1U, db()->metadata_count());
  945. ASSERT_TRUE(worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1)));
  946. const EntityData& out_entity2 =
  947. *worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1))->entity;
  948. const EntityMetadata metadata_v2 = db()->GetMetadata(kKey1);
  949. EXPECT_EQ(kValue2, out_entity2.specifics.preference().value());
  950. // Should still see old cid1 value, override is not respected on update.
  951. EXPECT_EQ(kId1, out_entity2.id);
  952. EXPECT_EQ(kId1, metadata_v2.server_id());
  953. EXPECT_EQ(metadata_v2.client_tag_hash(), out_entity2.client_tag_hash.value());
  954. // Specifics have changed so the hashes should not match.
  955. EXPECT_NE(metadata_v1.specifics_hash(), metadata_v2.specifics_hash());
  956. }
  957. // Creates a new local item, then modifies it after it has been acked.
  958. // Thoroughly tests data generated by modification of server-unknown item.
  959. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldCommitLocalUpdate) {
  960. InitializeToReadyState();
  961. WritePrefItem(bridge(), kKey1, kValue1);
  962. ASSERT_EQ(1U, db()->metadata_count());
  963. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  964. const EntityMetadata metadata_v1 = db()->GetMetadata(kKey1);
  965. int64_t request_data_v1_sequence_number;
  966. {
  967. // request_data_v1 is valid only while the commit is still pending.
  968. const CommitRequestData* request_data_v1 =
  969. worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1));
  970. ASSERT_TRUE(request_data_v1);
  971. const EntityData& data_v1 = *request_data_v1->entity;
  972. EXPECT_EQ(data_v1.specifics.preference().value(), kValue1);
  973. request_data_v1_sequence_number = request_data_v1->sequence_number;
  974. }
  975. worker()->AckOnePendingCommit();
  976. ASSERT_FALSE(type_processor()->IsEntityUnsynced(kKey1));
  977. const base::Time ctime = type_processor()->GetEntityCreationTime(kKey1);
  978. ASSERT_FALSE(ctime.is_null());
  979. ASSERT_EQ(ctime, type_processor()->GetEntityModificationTime(kKey1));
  980. // Make sure the clock advances.
  981. base::PlatformThread::Sleep(base::Milliseconds(1));
  982. ASSERT_NE(ctime, base::Time::Now());
  983. WritePrefItem(bridge(), kKey1, kValue2);
  984. EXPECT_EQ(1U, db()->metadata_count());
  985. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  986. EXPECT_TRUE(type_processor()->IsEntityUnsynced(kKey1));
  987. EXPECT_EQ(ctime, type_processor()->GetEntityCreationTime(kKey1));
  988. const base::Time mtime = type_processor()->GetEntityModificationTime(kKey1);
  989. EXPECT_NE(ctime, mtime);
  990. const CommitRequestData* request_data_v2 =
  991. worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1));
  992. ASSERT_TRUE(request_data_v2);
  993. const EntityData& data_v2 = *request_data_v2->entity;
  994. const EntityMetadata metadata_v2 = db()->GetMetadata(kKey1);
  995. // Test some of the relations between old and new commit requests.
  996. EXPECT_GT(request_data_v2->sequence_number, request_data_v1_sequence_number);
  997. EXPECT_EQ(data_v2.specifics.preference().value(), kValue2);
  998. // Perform a thorough examination of the update-generated request.
  999. EXPECT_NE(kUncommittedVersion, request_data_v2->base_version);
  1000. EXPECT_FALSE(data_v2.id.empty());
  1001. EXPECT_EQ(ctime, data_v2.creation_time);
  1002. EXPECT_EQ(mtime, data_v2.modification_time);
  1003. EXPECT_EQ(kKey1, data_v2.name);
  1004. EXPECT_FALSE(data_v2.is_deleted());
  1005. EXPECT_EQ(kKey1, data_v2.specifics.preference().name());
  1006. EXPECT_EQ(kValue2, data_v2.specifics.preference().value());
  1007. // Perform a thorough examination of the local sync metadata.
  1008. EXPECT_FALSE(metadata_v1.has_server_id());
  1009. EXPECT_FALSE(metadata_v1.is_deleted());
  1010. EXPECT_EQ(1, metadata_v1.sequence_number());
  1011. EXPECT_EQ(0, metadata_v1.acked_sequence_number());
  1012. EXPECT_EQ(kUncommittedVersion, metadata_v1.server_version());
  1013. EXPECT_FALSE(metadata_v2.server_id().empty());
  1014. EXPECT_FALSE(metadata_v2.is_deleted());
  1015. EXPECT_EQ(2, metadata_v2.sequence_number());
  1016. EXPECT_EQ(1, metadata_v2.acked_sequence_number());
  1017. EXPECT_NE(kUncommittedVersion, metadata_v2.server_version());
  1018. EXPECT_EQ(metadata_v1.client_tag_hash(), metadata_v2.client_tag_hash());
  1019. EXPECT_NE(metadata_v1.specifics_hash(), metadata_v2.specifics_hash());
  1020. }
  1021. // Same as above, but modifies the item BEFORE it has been acked.
  1022. // Thoroughly tests data generated by modification of server-unknown item.
  1023. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1024. ShouldCommitLocalUpdateBeforeCreationAck) {
  1025. InitializeToReadyState();
  1026. WritePrefItem(bridge(), kKey1, kValue1);
  1027. ASSERT_EQ(1U, db()->metadata_count());
  1028. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1029. const CommitRequestData* request_data_v1 =
  1030. worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1));
  1031. ASSERT_TRUE(request_data_v1);
  1032. const EntityData& data_v1 = *request_data_v1->entity;
  1033. const EntityMetadata metadata_v1 = db()->GetMetadata(kKey1);
  1034. ASSERT_TRUE(type_processor()->IsEntityUnsynced(kKey1));
  1035. const base::Time ctime = type_processor()->GetEntityCreationTime(kKey1);
  1036. ASSERT_EQ(ctime, type_processor()->GetEntityModificationTime(kKey1));
  1037. ASSERT_FALSE(ctime.is_null());
  1038. // Make sure the clock advances.
  1039. base::PlatformThread::Sleep(base::Milliseconds(1));
  1040. ASSERT_NE(ctime, base::Time::Now());
  1041. WritePrefItem(bridge(), kKey1, kValue2);
  1042. EXPECT_EQ(1U, db()->metadata_count());
  1043. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}, {GetPrefHash(kKey1)}});
  1044. EXPECT_TRUE(type_processor()->IsEntityUnsynced(kKey1));
  1045. EXPECT_EQ(ctime, type_processor()->GetEntityCreationTime(kKey1));
  1046. const base::Time mtime = type_processor()->GetEntityModificationTime(kKey1);
  1047. EXPECT_NE(mtime, ctime);
  1048. const CommitRequestData* request_data_v2 =
  1049. worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1));
  1050. ASSERT_TRUE(request_data_v2);
  1051. const EntityData& data_v2 = *request_data_v2->entity;
  1052. const EntityMetadata metadata_v2 = db()->GetMetadata(kKey1);
  1053. // Test some of the relations between old and new commit requests.
  1054. EXPECT_GT(request_data_v2->sequence_number, request_data_v1->sequence_number);
  1055. EXPECT_EQ(data_v1.specifics.preference().value(), kValue1);
  1056. // Perform a thorough examination of the update-generated request.
  1057. EXPECT_EQ(kUncommittedVersion, request_data_v2->base_version);
  1058. EXPECT_TRUE(data_v2.id.empty());
  1059. EXPECT_EQ(ctime, data_v2.creation_time);
  1060. EXPECT_EQ(mtime, data_v2.modification_time);
  1061. EXPECT_EQ(kKey1, data_v2.name);
  1062. EXPECT_FALSE(data_v2.is_deleted());
  1063. EXPECT_EQ(kKey1, data_v2.specifics.preference().name());
  1064. EXPECT_EQ(kValue2, data_v2.specifics.preference().value());
  1065. // Perform a thorough examination of the local sync metadata.
  1066. EXPECT_FALSE(metadata_v1.has_server_id());
  1067. EXPECT_FALSE(metadata_v1.is_deleted());
  1068. EXPECT_EQ(1, metadata_v1.sequence_number());
  1069. EXPECT_EQ(0, metadata_v1.acked_sequence_number());
  1070. EXPECT_EQ(kUncommittedVersion, metadata_v1.server_version());
  1071. EXPECT_FALSE(metadata_v2.has_server_id());
  1072. EXPECT_FALSE(metadata_v2.is_deleted());
  1073. EXPECT_EQ(2, metadata_v2.sequence_number());
  1074. EXPECT_EQ(0, metadata_v2.acked_sequence_number());
  1075. EXPECT_EQ(kUncommittedVersion, metadata_v2.server_version());
  1076. EXPECT_EQ(metadata_v1.client_tag_hash(), metadata_v2.client_tag_hash());
  1077. EXPECT_NE(metadata_v1.specifics_hash(), metadata_v2.specifics_hash());
  1078. }
  1079. // Tests that a local update that doesn't change specifics doesn't generate a
  1080. // commit request.
  1081. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldIgnoreRedundantLocalUpdate) {
  1082. InitializeToReadyState();
  1083. WritePrefItem(bridge(), kKey1, kValue1);
  1084. ASSERT_EQ(1U, db()->metadata_count());
  1085. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1086. const base::Time ctime = type_processor()->GetEntityCreationTime(kKey1);
  1087. const base::Time mtime = type_processor()->GetEntityModificationTime(kKey1);
  1088. ASSERT_FALSE(ctime.is_null());
  1089. ASSERT_FALSE(mtime.is_null());
  1090. WritePrefItem(bridge(), kKey1, kValue1);
  1091. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1092. EXPECT_EQ(ctime, type_processor()->GetEntityCreationTime(kKey1));
  1093. EXPECT_EQ(mtime, type_processor()->GetEntityModificationTime(kKey1));
  1094. }
  1095. // Test that an error applying changes from a server update is
  1096. // propagated to the error handler.
  1097. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldReportErrorApplyingUpdate) {
  1098. InitializeToReadyState();
  1099. bridge()->ErrorOnNextCall();
  1100. ExpectError(
  1101. ClientTagBasedModelTypeProcessor::ErrorSite::kApplyIncrementalUpdates);
  1102. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1103. GeneratePrefSpecifics(kKey1, kValue1));
  1104. }
  1105. // Tests locally deleting an acknowledged item.
  1106. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldCommitLocalDeletion) {
  1107. InitializeToReadyState();
  1108. WriteItemAndAck(kKey1, kValue1);
  1109. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  1110. const EntityMetadata metadata_v1 = db()->GetMetadata(kKey1);
  1111. EXPECT_FALSE(metadata_v1.is_deleted());
  1112. EXPECT_EQ(1, metadata_v1.sequence_number());
  1113. EXPECT_EQ(1, metadata_v1.acked_sequence_number());
  1114. EXPECT_EQ(1, metadata_v1.server_version());
  1115. bridge()->DeleteItem(kKey1);
  1116. EXPECT_EQ(0U, db()->data_count());
  1117. // Metadata is not removed until the commit response comes back.
  1118. EXPECT_EQ(1U, db()->metadata_count());
  1119. EXPECT_EQ(1U, ProcessorEntityCount());
  1120. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1121. const EntityMetadata metadata_v2 = db()->GetMetadata(kKey1);
  1122. EXPECT_TRUE(metadata_v2.is_deleted());
  1123. EXPECT_EQ(2, metadata_v2.sequence_number());
  1124. EXPECT_EQ(1, metadata_v2.acked_sequence_number());
  1125. EXPECT_EQ(1, metadata_v2.server_version());
  1126. // Ack the delete and check that the metadata is cleared.
  1127. worker()->AckOnePendingCommit();
  1128. EXPECT_EQ(0U, db()->metadata_count());
  1129. EXPECT_EQ(0U, ProcessorEntityCount());
  1130. // Create item again.
  1131. WriteItemAndAck(kKey1, kValue1);
  1132. const EntityMetadata metadata_v3 = db()->GetMetadata(kKey1);
  1133. EXPECT_FALSE(metadata_v3.is_deleted());
  1134. EXPECT_EQ(1, metadata_v3.sequence_number());
  1135. EXPECT_EQ(1, metadata_v3.acked_sequence_number());
  1136. EXPECT_EQ(3, metadata_v3.server_version());
  1137. }
  1138. // Tests that item created and deleted before sync cycle doesn't get committed.
  1139. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1140. ShouldNotCommitLocalDeletionOfUncommittedEntity) {
  1141. InitializeToMetadataLoaded();
  1142. WritePrefItem(bridge(), kKey1, kValue1);
  1143. bridge()->DeleteItem(kKey1);
  1144. OnSyncStarting();
  1145. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  1146. }
  1147. // Tests creating and deleting an item locally before receiving a commit
  1148. // response, then getting the commit responses.
  1149. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1150. ShouldHandleLocalDeletionDuringLocalCreationCommit) {
  1151. InitializeToReadyState();
  1152. WritePrefItem(bridge(), kKey1, kValue1);
  1153. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1154. const CommitRequestData* data_v1 =
  1155. worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1));
  1156. ASSERT_TRUE(data_v1);
  1157. const EntityMetadata metadata_v1 = db()->GetMetadata(kKey1);
  1158. EXPECT_FALSE(metadata_v1.is_deleted());
  1159. EXPECT_EQ(1, metadata_v1.sequence_number());
  1160. EXPECT_EQ(0, metadata_v1.acked_sequence_number());
  1161. EXPECT_EQ(kUncommittedVersion, metadata_v1.server_version());
  1162. bridge()->DeleteItem(kKey1);
  1163. EXPECT_EQ(0U, db()->data_count());
  1164. EXPECT_EQ(1U, db()->metadata_count());
  1165. EXPECT_EQ(1U, ProcessorEntityCount());
  1166. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}, {GetPrefHash(kKey1)}});
  1167. const CommitRequestData* data_v2 =
  1168. worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1));
  1169. ASSERT_TRUE(data_v2);
  1170. EXPECT_GT(data_v2->sequence_number, data_v1->sequence_number);
  1171. EXPECT_TRUE(data_v2->entity->id.empty());
  1172. EXPECT_EQ(kUncommittedVersion, data_v2->base_version);
  1173. EXPECT_TRUE(data_v2->entity->is_deleted());
  1174. const EntityMetadata metadata_v2 = db()->GetMetadata(kKey1);
  1175. EXPECT_TRUE(metadata_v2.is_deleted());
  1176. EXPECT_EQ(2, metadata_v2.sequence_number());
  1177. EXPECT_EQ(0, metadata_v2.acked_sequence_number());
  1178. EXPECT_EQ(kUncommittedVersion, metadata_v2.server_version());
  1179. // A response for the first commit doesn't change much.
  1180. worker()->AckOnePendingCommit();
  1181. EXPECT_EQ(0U, db()->data_count());
  1182. EXPECT_EQ(1U, db()->metadata_count());
  1183. EXPECT_EQ(1U, ProcessorEntityCount());
  1184. const EntityMetadata metadata_v3 = db()->GetMetadata(kKey1);
  1185. EXPECT_TRUE(metadata_v3.is_deleted());
  1186. EXPECT_EQ(2, metadata_v3.sequence_number());
  1187. EXPECT_EQ(1, metadata_v3.acked_sequence_number());
  1188. EXPECT_EQ(1, metadata_v3.server_version());
  1189. worker()->AckOnePendingCommit();
  1190. // The delete was acked so the metadata should now be cleared.
  1191. EXPECT_EQ(0U, db()->metadata_count());
  1192. EXPECT_EQ(0U, ProcessorEntityCount());
  1193. }
  1194. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldProcessRemoteDeletion) {
  1195. InitializeToReadyState();
  1196. WriteItemAndAck(kKey1, kValue1);
  1197. EXPECT_EQ(1U, ProcessorEntityCount());
  1198. EXPECT_EQ(1U, db()->metadata_count());
  1199. EXPECT_EQ(1U, db()->data_count());
  1200. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  1201. worker()->TombstoneFromServer(GetPrefHash(kKey1));
  1202. // Delete from server should clear the data and all the metadata.
  1203. EXPECT_EQ(0U, db()->data_count());
  1204. EXPECT_EQ(0U, db()->metadata_count());
  1205. EXPECT_EQ(0U, ProcessorEntityCount());
  1206. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  1207. // Create item again.
  1208. WriteItemAndAck(kKey1, kValue1);
  1209. const EntityMetadata metadata = db()->GetMetadata(kKey1);
  1210. EXPECT_FALSE(metadata.is_deleted());
  1211. EXPECT_EQ(1, metadata.sequence_number());
  1212. EXPECT_EQ(1, metadata.acked_sequence_number());
  1213. EXPECT_EQ(3, metadata.server_version());
  1214. }
  1215. // Deletes an item we've never seen before.
  1216. // Should have no effect and not crash.
  1217. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1218. ShouldIgnoreLocalDeletionOfUnknownEntity) {
  1219. InitializeToReadyState();
  1220. bridge()->DeleteItem(kKey1);
  1221. EXPECT_EQ(0U, db()->data_count());
  1222. EXPECT_EQ(0U, db()->metadata_count());
  1223. EXPECT_EQ(0U, ProcessorEntityCount());
  1224. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  1225. }
  1226. // Tests that after committing entity fails, processor includes this entity in
  1227. // consecutive commits.
  1228. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1229. ShouldRetryCommitAfterServerError) {
  1230. InitializeToReadyState();
  1231. WritePrefItem(bridge(), kKey1, kValue1);
  1232. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1233. // Entity is sent to server. Processor shouldn't include it in local changes.
  1234. CommitRequestDataList commit_request;
  1235. type_processor()->GetLocalChanges(
  1236. INT_MAX, base::BindOnce(&CaptureCommitRequest, &commit_request));
  1237. EXPECT_TRUE(commit_request.empty());
  1238. // Fail commit from worker side indicating this entity was not committed.
  1239. // Processor should include it in consecutive GetLocalChanges responses.
  1240. worker()->FailOneCommit();
  1241. type_processor()->GetLocalChanges(
  1242. INT_MAX, base::BindOnce(&CaptureCommitRequest, &commit_request));
  1243. OnCommitDataLoaded();
  1244. EXPECT_EQ(1U, commit_request.size());
  1245. EXPECT_EQ(GetPrefHash(kKey1), commit_request[0]->entity->client_tag_hash);
  1246. }
  1247. // Tests that after committing entity fails, processor includes this entity in
  1248. // consecutive commits. This test differs from the above one for the case when
  1249. // there is an HTTP error.
  1250. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1251. ShouldRetryCommitAfterFullCommitFailure) {
  1252. InitializeToReadyState();
  1253. bridge()->EnableRetriesOnCommitFailure();
  1254. WritePrefItem(bridge(), kKey1, kValue1);
  1255. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1256. // Entity is sent to server. Processor shouldn't include it in local changes.
  1257. CommitRequestDataList commit_request;
  1258. type_processor()->GetLocalChanges(
  1259. INT_MAX, base::BindOnce(&CaptureCommitRequest, &commit_request));
  1260. EXPECT_TRUE(commit_request.empty());
  1261. // Fail commit from worker side indicating this entity was not committed.
  1262. // Processor should include it in consecutive GetLocalChanges responses.
  1263. worker()->FailFullCommitRequest();
  1264. type_processor()->GetLocalChanges(
  1265. INT_MAX, base::BindOnce(&CaptureCommitRequest, &commit_request));
  1266. OnCommitDataLoaded();
  1267. ASSERT_EQ(1U, commit_request.size());
  1268. EXPECT_EQ(GetPrefHash(kKey1), commit_request[0]->entity->client_tag_hash);
  1269. }
  1270. // Tests that GetLocalChanges honors max_entries parameter.
  1271. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1272. ShouldTruncateLocalChangesToMaxSize) {
  1273. InitializeToMetadataLoaded();
  1274. WritePrefItem(bridge(), kKey1, kValue1);
  1275. WritePrefItem(bridge(), kKey2, kValue2);
  1276. // Reqeust at most one intity per batch, ensure that only one was returned.
  1277. CommitRequestDataList commit_request;
  1278. type_processor()->GetLocalChanges(
  1279. 1, base::BindOnce(&CaptureCommitRequest, &commit_request));
  1280. EXPECT_EQ(1U, commit_request.size());
  1281. }
  1282. // Creates two different sync items.
  1283. // Verifies that the second has no effect on the first.
  1284. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldHandleTwoIndependentItems) {
  1285. InitializeToReadyState();
  1286. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  1287. WritePrefItem(bridge(), kKey1, kValue1);
  1288. EXPECT_EQ(1U, db()->data_count());
  1289. EXPECT_EQ(1U, db()->metadata_count());
  1290. const EntityMetadata metadata1 = db()->GetMetadata(kKey1);
  1291. // There should be one commit request for this item only.
  1292. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1293. WritePrefItem(bridge(), kKey2, kValue2);
  1294. EXPECT_EQ(2U, db()->data_count());
  1295. EXPECT_EQ(2U, db()->metadata_count());
  1296. const EntityMetadata metadata2 = db()->GetMetadata(kKey2);
  1297. // The second write should trigger another single-item commit request.
  1298. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}, {GetPrefHash(kKey2)}});
  1299. EXPECT_FALSE(metadata1.is_deleted());
  1300. EXPECT_EQ(1, metadata1.sequence_number());
  1301. EXPECT_EQ(0, metadata1.acked_sequence_number());
  1302. EXPECT_EQ(kUncommittedVersion, metadata1.server_version());
  1303. EXPECT_FALSE(metadata2.is_deleted());
  1304. EXPECT_EQ(1, metadata2.sequence_number());
  1305. EXPECT_EQ(0, metadata2.acked_sequence_number());
  1306. EXPECT_EQ(kUncommittedVersion, metadata2.server_version());
  1307. }
  1308. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1309. ShouldNotTreatMatchingChangesAsConflict) {
  1310. InitializeToReadyState();
  1311. EntitySpecifics specifics = WritePrefItem(bridge(), kKey1, kValue1);
  1312. EXPECT_EQ(1U, db()->data_change_count());
  1313. EXPECT_EQ(kValue1, GetPrefValue(db()->GetData(kKey1)));
  1314. EXPECT_EQ(1U, db()->metadata_change_count());
  1315. EXPECT_EQ(kUncommittedVersion, db()->GetMetadata(kKey1).server_version());
  1316. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1317. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics});
  1318. // Changes match doesn't call ResolveConflict.
  1319. worker()->UpdateFromServer(GetPrefHash(kKey1), specifics);
  1320. // Updated metadata but not data; no new commit request.
  1321. EXPECT_EQ(1U, db()->data_change_count());
  1322. EXPECT_EQ(1, db()->GetMetadata(kKey1).server_version());
  1323. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1324. }
  1325. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1326. ShouldResolveConflictToLocalVersion) {
  1327. InitializeToReadyState();
  1328. // WriteAndAck entity to get id from the server.
  1329. WriteItemAndAck(kKey1, kValue1);
  1330. bridge()->SetConflictResolution(ConflictResolution::kUseLocal);
  1331. // Change value locally and at the same time simulate conflicting update from
  1332. // server.
  1333. EntitySpecifics specifics2 = WritePrefItem(bridge(), kKey1, kValue2);
  1334. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1335. GeneratePrefSpecifics(kKey1, kValue3));
  1336. OnCommitDataLoaded();
  1337. // Updated metadata but not data; new commit request.
  1338. EXPECT_EQ(2U, db()->data_change_count());
  1339. EXPECT_EQ(4U, db()->metadata_change_count());
  1340. EXPECT_EQ(2, db()->GetMetadata(kKey1).server_version());
  1341. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}, {GetPrefHash(kKey1)}});
  1342. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1)}, {specifics2});
  1343. }
  1344. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1345. ShouldResolveConflictToLocalUndeletion) {
  1346. InitializeToReadyState();
  1347. ASSERT_EQ(0U, worker()->GetNumPendingCommits());
  1348. WritePrefItem(bridge(), kKey1, kValue1);
  1349. ASSERT_EQ(1U, worker()->GetNumPendingCommits());
  1350. ASSERT_TRUE(worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1)));
  1351. ASSERT_TRUE(worker()
  1352. ->GetLatestPendingCommitForHash(GetPrefHash(kKey1))
  1353. ->entity->id.empty());
  1354. // The update from the server should be mostly ignored because local wins, but
  1355. // the server ID should be updated.
  1356. bridge()->SetConflictResolution(ConflictResolution::kUseLocal);
  1357. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1358. GeneratePrefSpecifics(kKey1, kValue3));
  1359. OnCommitDataLoaded();
  1360. // In this test setup, the processor's nudge for commit immediately pulls
  1361. // updates from the processor and list them as pending commits, so we should
  1362. // see two commits at this point.
  1363. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  1364. // Verify the commit request this operation has triggered.
  1365. const CommitRequestData* tag1_request_data =
  1366. worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1));
  1367. ASSERT_TRUE(tag1_request_data);
  1368. const EntityData& tag1_data = *tag1_request_data->entity;
  1369. EXPECT_EQ(1, tag1_request_data->base_version);
  1370. EXPECT_FALSE(tag1_data.id.empty());
  1371. EXPECT_FALSE(tag1_data.creation_time.is_null());
  1372. EXPECT_FALSE(tag1_data.modification_time.is_null());
  1373. EXPECT_EQ(kKey1, tag1_data.name);
  1374. EXPECT_FALSE(tag1_data.is_deleted());
  1375. EXPECT_EQ(kKey1, tag1_data.specifics.preference().name());
  1376. EXPECT_EQ(kValue1, tag1_data.specifics.preference().value());
  1377. EXPECT_EQ(1U, db()->metadata_count());
  1378. const EntityMetadata metadata = db()->GetMetadata(kKey1);
  1379. EXPECT_TRUE(metadata.has_client_tag_hash());
  1380. EXPECT_TRUE(metadata.has_server_id());
  1381. EXPECT_FALSE(metadata.is_deleted());
  1382. EXPECT_EQ(1, metadata.sequence_number());
  1383. EXPECT_EQ(0, metadata.acked_sequence_number());
  1384. EXPECT_EQ(1, metadata.server_version());
  1385. EXPECT_TRUE(metadata.has_creation_time());
  1386. EXPECT_TRUE(metadata.has_modification_time());
  1387. EXPECT_TRUE(metadata.has_specifics_hash());
  1388. }
  1389. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1390. ShouldResolveConflictToRemoteUndeletion) {
  1391. InitializeToReadyState();
  1392. WriteItemAndAck(kKey1, kValue1);
  1393. ASSERT_EQ(0U, worker()->GetNumPendingCommits());
  1394. bridge()->DeleteItem(kKey1);
  1395. ASSERT_EQ(1U, worker()->GetNumPendingCommits());
  1396. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1397. ASSERT_TRUE(worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1)));
  1398. ASSERT_TRUE(worker()
  1399. ->GetLatestPendingCommitForHash(GetPrefHash(kKey1))
  1400. ->entity->is_deleted());
  1401. ASSERT_EQ(2U, db()->data_change_count());
  1402. ASSERT_EQ(3U, db()->metadata_change_count());
  1403. ASSERT_TRUE(type_processor()->IsTrackingEntityForTest(kKey1));
  1404. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1405. GeneratePrefSpecifics(kKey1, kValue2));
  1406. // Updated client data and metadata; no new commit request.
  1407. EXPECT_TRUE(type_processor()->IsTrackingEntityForTest(kKey1));
  1408. EXPECT_EQ(3U, db()->data_change_count());
  1409. EXPECT_EQ(kValue2, GetPrefValue(db()->GetData(kKey1)));
  1410. EXPECT_EQ(4U, db()->metadata_change_count());
  1411. EXPECT_EQ(2, db()->GetMetadata(kKey1).server_version());
  1412. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1413. }
  1414. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1415. ShouldResolveConflictToRemoteUndeletionWithUpdateStorageKey) {
  1416. bridge()->SetSupportsGetStorageKey(false);
  1417. InitializeToReadyState();
  1418. WriteItemAndAck(kKey1, kValue1);
  1419. ASSERT_EQ(0U, worker()->GetNumPendingCommits());
  1420. bridge()->DeleteItem(kKey1);
  1421. ASSERT_EQ(1U, worker()->GetNumPendingCommits());
  1422. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1423. ASSERT_TRUE(worker()->GetLatestPendingCommitForHash(GetPrefHash(kKey1)));
  1424. ASSERT_TRUE(worker()
  1425. ->GetLatestPendingCommitForHash(GetPrefHash(kKey1))
  1426. ->entity->is_deleted());
  1427. ASSERT_EQ(2U, db()->data_change_count());
  1428. ASSERT_EQ(3U, db()->metadata_change_count());
  1429. ASSERT_TRUE(type_processor()->IsTrackingEntityForTest(kKey1));
  1430. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1431. GeneratePrefSpecifics(kKey1, kValue2));
  1432. // A new storage key should have been generated, which should replace the
  1433. // previous when it comes to storing data and metadata.
  1434. const std::string new_storage_key = bridge()->GetLastGeneratedStorageKey();
  1435. ASSERT_NE(kKey1, new_storage_key);
  1436. EXPECT_TRUE(db()->HasData(new_storage_key));
  1437. EXPECT_TRUE(db()->HasMetadata(new_storage_key));
  1438. EXPECT_TRUE(type_processor()->IsTrackingEntityForTest(new_storage_key));
  1439. EXPECT_FALSE(db()->HasData(kKey1));
  1440. EXPECT_FALSE(db()->HasMetadata(kKey1));
  1441. EXPECT_FALSE(type_processor()->IsTrackingEntityForTest(kKey1));
  1442. // Updated client data and metadata; no new commit request.
  1443. EXPECT_EQ(3U, db()->data_change_count());
  1444. EXPECT_EQ(kValue2, GetPrefValue(db()->GetData(new_storage_key)));
  1445. EXPECT_EQ(5U, db()->metadata_change_count());
  1446. EXPECT_EQ(2, db()->GetMetadata(new_storage_key).server_version());
  1447. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1448. }
  1449. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1450. ShouldResolveConflictToRemoteVersion) {
  1451. InitializeToReadyState();
  1452. WritePrefItem(bridge(), kKey1, kValue1);
  1453. bridge()->SetConflictResolution(ConflictResolution::kUseRemote);
  1454. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1455. GeneratePrefSpecifics(kKey1, kValue2));
  1456. // Updated client data and metadata; no new commit request.
  1457. EXPECT_EQ(2U, db()->data_change_count());
  1458. EXPECT_EQ(kValue2, GetPrefValue(db()->GetData(kKey1)));
  1459. EXPECT_EQ(2U, db()->metadata_change_count());
  1460. EXPECT_EQ(1, db()->GetMetadata(kKey1).server_version());
  1461. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1462. }
  1463. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1464. ShouldResolveConflictToRemoteDeletion) {
  1465. InitializeToReadyState();
  1466. WritePrefItem(bridge(), kKey1, kValue1);
  1467. bridge()->SetConflictResolution(ConflictResolution::kUseRemote);
  1468. worker()->TombstoneFromServer(GetPrefHash(kKey1));
  1469. // Updated client data and metadata; no new commit request.
  1470. EXPECT_EQ(0U, db()->data_count());
  1471. EXPECT_EQ(0U, db()->metadata_count());
  1472. EXPECT_EQ(2U, db()->data_change_count());
  1473. EXPECT_EQ(2U, db()->metadata_change_count());
  1474. }
  1475. // Test proper handling of disconnect and reconnect.
  1476. //
  1477. // Creates items in various states of commit and verifies they re-attempt to
  1478. // commit on reconnect.
  1479. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldDisconnectAndReconnect) {
  1480. InitializeToReadyState();
  1481. // The first item is fully committed.
  1482. WriteItemAndAck(kKey1, kValue1);
  1483. // The second item has a commit request in progress.
  1484. WritePrefItem(bridge(), kKey2, kValue2);
  1485. EXPECT_TRUE(worker()->HasPendingCommitForHash(GetPrefHash(kKey2)));
  1486. DisconnectSync();
  1487. // The third item is added after stopping.
  1488. WritePrefItem(bridge(), kKey3, kValue3);
  1489. // Reconnect.
  1490. OnSyncStarting();
  1491. OnCommitDataLoaded();
  1492. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  1493. EXPECT_EQ(2U, worker()->GetNthPendingCommit(0).size());
  1494. // The first item was already in sync.
  1495. EXPECT_FALSE(worker()->HasPendingCommitForHash(GetPrefHash(kKey1)));
  1496. // The second item's commit was interrupted and should be retried.
  1497. EXPECT_TRUE(worker()->HasPendingCommitForHash(GetPrefHash(kKey2)));
  1498. // The third item's commit was not started until the reconnect.
  1499. EXPECT_TRUE(worker()->HasPendingCommitForHash(GetPrefHash(kKey3)));
  1500. }
  1501. // Test proper handling of stop (without disabling sync) and re-enable.
  1502. //
  1503. // Creates items in various states of commit and verifies they do NOT attempt to
  1504. // commit on re-enable.
  1505. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldStopAndKeepMetadata) {
  1506. InitializeToReadyState();
  1507. // The first item is fully committed.
  1508. WriteItemAndAck(kKey1, kValue1);
  1509. // The second item has a commit request in progress.
  1510. WritePrefItem(bridge(), kKey2, kValue2);
  1511. EXPECT_TRUE(worker()->HasPendingCommitForHash(GetPrefHash(kKey2)));
  1512. type_processor()->OnSyncStopping(KEEP_METADATA);
  1513. EXPECT_TRUE(type_processor()->IsTrackingMetadata());
  1514. // The third item is added after disable.
  1515. WritePrefItem(bridge(), kKey3, kValue3);
  1516. // Now we re-enable.
  1517. OnSyncStarting();
  1518. worker()->UpdateFromServer();
  1519. // Once we're ready to commit, only the newest items should be committed.
  1520. worker()->VerifyPendingCommits({{GetPrefHash(kKey3)}});
  1521. }
  1522. // Test proper handling of disable and re-enable.
  1523. //
  1524. // Creates items in various states of commit and verifies they re-attempt to
  1525. // commit on re-enable.
  1526. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldStopAndClearMetadata) {
  1527. InitializeToReadyState();
  1528. // The first item is fully committed.
  1529. WriteItemAndAck(kKey1, kValue1);
  1530. // The second item has a commit request in progress.
  1531. WritePrefItem(bridge(), kKey2, kValue2);
  1532. EXPECT_TRUE(worker()->HasPendingCommitForHash(GetPrefHash(kKey2)));
  1533. type_processor()->OnSyncStopping(CLEAR_METADATA);
  1534. EXPECT_FALSE(type_processor()->IsTrackingMetadata());
  1535. // The third item is added after disable.
  1536. WritePrefItem(bridge(), kKey3, kValue3);
  1537. // Now we re-enable.
  1538. OnSyncStarting();
  1539. worker()->UpdateFromServer();
  1540. EXPECT_TRUE(type_processor()->IsTrackingMetadata());
  1541. // Once we're ready to commit, all three local items should consider
  1542. // themselves uncommitted and pending for commit.
  1543. worker()->VerifyPendingCommits(
  1544. {{GetPrefHash(kKey1)}, {GetPrefHash(kKey2)}, {GetPrefHash(kKey3)}});
  1545. }
  1546. // Test proper handling of disable-sync before initial sync done.
  1547. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1548. ShouldNotClearBridgeMetadataPriorToMergeSyncData) {
  1549. // Populate the bridge's metadata with some non-empty values for us to later
  1550. // check that it hasn't been cleared.
  1551. const std::string kTestEncryptionKeyName = "TestEncryptionKey";
  1552. ModelTypeState model_type_state(db()->model_type_state());
  1553. model_type_state.set_encryption_key_name(kTestEncryptionKeyName);
  1554. bridge()->mutable_db()->set_model_type_state(model_type_state);
  1555. ModelReadyToSync();
  1556. OnSyncStarting();
  1557. ASSERT_FALSE(type_processor()->IsTrackingMetadata());
  1558. type_processor()->OnSyncStopping(CLEAR_METADATA);
  1559. EXPECT_FALSE(type_processor()->IsTrackingMetadata());
  1560. EXPECT_EQ(kTestEncryptionKeyName,
  1561. db()->model_type_state().encryption_key_name());
  1562. }
  1563. // Test re-encrypt everything when desired encryption key changes.
  1564. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldReencryptCommitsWithNewKey) {
  1565. InitializeToReadyState();
  1566. // Commit an item.
  1567. EntitySpecifics specifics1 = WriteItemAndAck(kKey1, kValue1);
  1568. // Create another item and don't wait for its commit response.
  1569. EntitySpecifics specifics2 = WritePrefItem(bridge(), kKey2, kValue2);
  1570. worker()->VerifyPendingCommits({{GetPrefHash(kKey2)}});
  1571. EXPECT_EQ(1U, db()->GetMetadata(kKey1).sequence_number());
  1572. EXPECT_EQ(1U, db()->GetMetadata(kKey2).sequence_number());
  1573. // Receive notice that the account's desired encryption key has changed.
  1574. worker()->UpdateWithEncryptionKey("k1");
  1575. // No pending commits because Tag 1 requires data load.
  1576. ASSERT_EQ(1U, worker()->GetNumPendingCommits());
  1577. // Tag 1 needs to go to the store to load its data before recommitting.
  1578. OnCommitDataLoaded();
  1579. // All data are in memory now.
  1580. ASSERT_EQ(2U, worker()->GetNumPendingCommits());
  1581. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1), GetPrefHash(kKey2)},
  1582. {specifics1, specifics2});
  1583. // Sequence numbers in the store are updated.
  1584. EXPECT_EQ(2U, db()->GetMetadata(kKey1).sequence_number());
  1585. EXPECT_EQ(2U, db()->GetMetadata(kKey2).sequence_number());
  1586. }
  1587. // Test that an error loading pending commit data for re-encryption is
  1588. // propagated to the error handler.
  1589. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1590. ShouldHandleErrorWhileReencrypting) {
  1591. InitializeToReadyState();
  1592. WriteItemAndAck(kKey1, kValue1);
  1593. bridge()->ErrorOnNextCall();
  1594. ExpectError(
  1595. ClientTagBasedModelTypeProcessor::ErrorSite::kApplyIncrementalUpdates);
  1596. worker()->UpdateWithEncryptionKey("k1");
  1597. }
  1598. // Test receipt of updates with new and old keys.
  1599. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldReencryptUpdatesWithNewKey) {
  1600. InitializeToReadyState();
  1601. // Receive an unencrypted update.
  1602. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1603. GeneratePrefSpecifics(kKey1, kValue1));
  1604. ASSERT_EQ(0U, worker()->GetNumPendingCommits());
  1605. UpdateResponseDataList update;
  1606. // Receive an entity with old encryption as part of the update.
  1607. update.push_back(worker()->GenerateUpdateData(
  1608. GetPrefHash(kKey2), GeneratePrefSpecifics(kKey2, kValue2), 1, "k1"));
  1609. // Receive an entity with up-to-date encryption as part of the update.
  1610. update.push_back(worker()->GenerateUpdateData(
  1611. GetPrefHash(kKey3), GeneratePrefSpecifics(kKey3, kValue3), 1, "k2"));
  1612. // Set desired encryption key to k2 to force updates to some items.
  1613. worker()->UpdateWithEncryptionKey("k2", std::move(update));
  1614. OnCommitDataLoaded();
  1615. // kKey1 needed data so once that's loaded, kKey1 and kKey2 are queued for
  1616. // commit.
  1617. worker()->VerifyPendingCommits({{GetPrefHash(kKey1), GetPrefHash(kKey2)}});
  1618. // Receive a separate update that was encrypted with key k1.
  1619. worker()->UpdateFromServer(GetPrefHash(kKey4),
  1620. GeneratePrefSpecifics(kKey4, kValue1), 1, "k1");
  1621. OnCommitDataLoaded();
  1622. // Receipt of updates encrypted with old key also forces a re-encrypt commit.
  1623. worker()->VerifyPendingCommits(
  1624. {{GetPrefHash(kKey1), GetPrefHash(kKey2)}, {GetPrefHash(kKey4)}});
  1625. // Receive an update that was encrypted with key k2.
  1626. worker()->UpdateFromServer(GetPrefHash(kKey5),
  1627. GeneratePrefSpecifics(kKey5, kValue1), 1, "k2");
  1628. // That was the correct key, so no re-encryption is required.
  1629. worker()->VerifyPendingCommits(
  1630. {{GetPrefHash(kKey1), GetPrefHash(kKey2)}, {GetPrefHash(kKey4)}});
  1631. }
  1632. // Test that re-encrypting enqueues the right data for kUseLocal conflicts.
  1633. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1634. ShouldResolveConflictToLocalDuringReencryption) {
  1635. InitializeToReadyState();
  1636. // WriteAndAck entity to get id from the server.
  1637. WriteItemAndAck(kKey1, kValue1);
  1638. worker()->UpdateWithEncryptionKey("k1");
  1639. OnCommitDataLoaded();
  1640. EntitySpecifics specifics = WritePrefItem(bridge(), kKey1, kValue2);
  1641. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}, {GetPrefHash(kKey1)}});
  1642. bridge()->SetConflictResolution(ConflictResolution::kUseLocal);
  1643. // Unencrypted update needs to be re-commited with key k1.
  1644. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1645. GeneratePrefSpecifics(kKey1, kValue3), 1, "");
  1646. OnCommitDataLoaded();
  1647. // Ensure the re-commit has the correct value.
  1648. EXPECT_EQ(3U, worker()->GetNumPendingCommits());
  1649. worker()->VerifyNthPendingCommit(2, {GetPrefHash(kKey1)}, {specifics});
  1650. EXPECT_EQ(kValue2, GetPrefValue(db()->GetData(kKey1)));
  1651. }
  1652. // Test that re-encrypting enqueues the right data for kUseRemote conflicts.
  1653. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1654. ShouldResolveConflictToRemoteDuringReencryption) {
  1655. InitializeToReadyState();
  1656. worker()->UpdateWithEncryptionKey("k1");
  1657. WritePrefItem(bridge(), kKey1, kValue1);
  1658. bridge()->SetConflictResolution(ConflictResolution::kUseRemote);
  1659. // Unencrypted update needs to be re-commited with key k1.
  1660. EntitySpecifics specifics = GeneratePrefSpecifics(kKey1, kValue2);
  1661. worker()->UpdateFromServer(GetPrefHash(kKey1), specifics, 1, "");
  1662. OnCommitDataLoaded();
  1663. // Ensure the re-commit has the correct value.
  1664. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  1665. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1)}, {specifics});
  1666. EXPECT_EQ(kValue2, GetPrefValue(db()->GetData(kKey1)));
  1667. }
  1668. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1669. ShouldHandleConflictWhileLoadingForReencryption) {
  1670. InitializeToReadyState();
  1671. // Create item and ack so its data is no longer cached.
  1672. WriteItemAndAck(kKey1, kValue1);
  1673. // Update key so that it needs to fetch data to re-commit.
  1674. worker()->UpdateWithEncryptionKey("k1");
  1675. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  1676. OnCommitDataLoaded();
  1677. // Unencrypted update needs to be re-commited with key k1.
  1678. EntitySpecifics specifics = GeneratePrefSpecifics(kKey1, kValue2);
  1679. worker()->UpdateFromServer(GetPrefHash(kKey1), specifics, 1, "");
  1680. OnCommitDataLoaded();
  1681. // Ensure the re-commit has the correct value.
  1682. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  1683. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1)}, {specifics});
  1684. EXPECT_EQ(kValue2, GetPrefValue(db()->GetData(kKey1)));
  1685. }
  1686. // Tests that a real remote change wins over a local encryption-only change.
  1687. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1688. ShouldIgnoreLocalEncryptionChange) {
  1689. InitializeToReadyState();
  1690. EntitySpecifics specifics = WriteItemAndAck(kKey1, kValue1);
  1691. worker()->UpdateWithEncryptionKey("k1");
  1692. OnCommitDataLoaded();
  1693. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  1694. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics});
  1695. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1696. GeneratePrefSpecifics(kKey1, kValue2));
  1697. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  1698. }
  1699. // Tests that updates without client tags get dropped.
  1700. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1701. ShouldDropRemoteUpdatesWithoutClientTags) {
  1702. InitializeToReadyState();
  1703. UpdateResponseDataList updates;
  1704. updates.push_back(worker()->GenerateUpdateData(
  1705. ClientTagHash(), GeneratePrefSpecifics(kKey1, kValue1), 1, "k1"));
  1706. worker()->UpdateFromServer(std::move(updates));
  1707. // Verify that the data wasn't actually stored.
  1708. EXPECT_EQ(0U, db()->metadata_count());
  1709. EXPECT_EQ(0U, db()->data_count());
  1710. }
  1711. // Tests that initial updates for transport-only mode (called "ephemeral
  1712. // storage" for historical reasons) result in reporting setup duration.
  1713. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1714. ShouldReportEphemeralConfigurationTime) {
  1715. InitializeToMetadataLoaded(/*initial_sync_done=*/false);
  1716. OnSyncStarting(kDefaultAuthenticatedAccountId, kCacheGuid,
  1717. SyncMode::kTransportOnly);
  1718. base::HistogramTester histogram_tester;
  1719. UpdateResponseDataList updates;
  1720. updates.push_back(worker()->GenerateUpdateData(
  1721. ClientTagHash(), GeneratePrefSpecifics(kKey1, kValue1), 1, "k1"));
  1722. worker()->UpdateFromServer(std::move(updates));
  1723. ASSERT_EQ(1, bridge()->merge_call_count());
  1724. // The duration should get recorded into the right histogram.
  1725. histogram_tester.ExpectTotalCount(
  1726. "Sync.ModelTypeConfigurationTime.Ephemeral.PREFERENCE",
  1727. /*count=*/1);
  1728. histogram_tester.ExpectTotalCount(
  1729. "Sync.ModelTypeConfigurationTime.Persistent.PREFERENCE",
  1730. /*count=*/0);
  1731. }
  1732. // Tests that initial updates for full-sync mode (called "persistent storage"
  1733. // for historical reasons) do not result in reporting setup duration.
  1734. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1735. ShouldReportPersistentConfigurationTime) {
  1736. InitializeToMetadataLoaded(/*initial_sync_done=*/false);
  1737. OnSyncStarting();
  1738. base::HistogramTester histogram_tester;
  1739. UpdateResponseDataList updates;
  1740. updates.push_back(worker()->GenerateUpdateData(
  1741. ClientTagHash(), GeneratePrefSpecifics(kKey1, kValue1), 1, "k1"));
  1742. worker()->UpdateFromServer(std::move(updates));
  1743. ASSERT_EQ(1, bridge()->merge_call_count());
  1744. // The duration should get recorded into the right histogram.
  1745. histogram_tester.ExpectTotalCount(
  1746. "Sync.ModelTypeConfigurationTime.Ephemeral.PREFERENCE",
  1747. /*count=*/0);
  1748. histogram_tester.ExpectTotalCount(
  1749. "Sync.ModelTypeConfigurationTime.Persistent.PREFERENCE",
  1750. /*count=*/1);
  1751. }
  1752. class FullUpdateClientTagBasedModelTypeProcessorTest
  1753. : public ClientTagBasedModelTypeProcessorTest {
  1754. protected:
  1755. bool SupportsIncrementalUpdates() override { return false; }
  1756. };
  1757. // Tests that ClientTagBasedModelTypeProcessor can do garbage collection by
  1758. // version.
  1759. // Garbage collection by version is used by the server to replace all data on
  1760. // the client, and is implemented by calling MergeSyncData on the bridge.
  1761. TEST_F(FullUpdateClientTagBasedModelTypeProcessorTest,
  1762. ShouldApplyGarbageCollectionByVersionFullUpdate) {
  1763. InitializeToReadyState();
  1764. UpdateResponseDataList updates;
  1765. updates.push_back(worker()->GenerateUpdateData(
  1766. ClientTagHash(), GeneratePrefSpecifics(kKey1, kValue1), 1, "k1"));
  1767. updates.push_back(worker()->GenerateUpdateData(
  1768. ClientTagHash(), GeneratePrefSpecifics(kKey2, kValue2), 2, "k2"));
  1769. // Create 2 entries, one is version 3, another is version 1.
  1770. sync_pb::GarbageCollectionDirective garbage_collection_directive;
  1771. garbage_collection_directive.set_version_watermark(1);
  1772. worker()->UpdateWithGarbageCollection(std::move(updates),
  1773. garbage_collection_directive);
  1774. WriteItemAndAck(kKey1, kValue1);
  1775. WriteItemAndAck(kKey2, kValue2);
  1776. // Verify entries are created correctly.
  1777. ASSERT_EQ(2U, ProcessorEntityCount());
  1778. ASSERT_EQ(2U, db()->metadata_count());
  1779. ASSERT_EQ(2U, db()->data_count());
  1780. ASSERT_EQ(0U, worker()->GetNumPendingCommits());
  1781. ASSERT_EQ(1, bridge()->merge_call_count());
  1782. // Tell the client to delete all data.
  1783. sync_pb::GarbageCollectionDirective new_directive;
  1784. new_directive.set_version_watermark(2);
  1785. worker()->UpdateWithGarbageCollection(new_directive);
  1786. // Verify that merge is called on the bridge to replace the current sync data.
  1787. EXPECT_EQ(2, bridge()->merge_call_count());
  1788. // Verify that the processor cleared all metadata.
  1789. EXPECT_EQ(0U, db()->metadata_count());
  1790. EXPECT_EQ(0U, worker()->GetNumPendingCommits());
  1791. }
  1792. // Tests that full updates for transport-only mode (called "ephemeral storage"
  1793. // for historical reasons) result in reporting setup duration.
  1794. TEST_F(FullUpdateClientTagBasedModelTypeProcessorTest,
  1795. ShouldReportEphemeralConfigurationTimeOnlyForFirstFullUpdate) {
  1796. InitializeToMetadataLoaded(/*initial_sync_done=*/false);
  1797. OnSyncStarting(kDefaultAuthenticatedAccountId, kCacheGuid,
  1798. SyncMode::kTransportOnly);
  1799. UpdateResponseDataList updates1;
  1800. updates1.push_back(worker()->GenerateUpdateData(
  1801. ClientTagHash(), GeneratePrefSpecifics(kKey1, kValue1), 1, "k1"));
  1802. sync_pb::GarbageCollectionDirective garbage_collection_directive;
  1803. garbage_collection_directive.set_version_watermark(1);
  1804. {
  1805. base::HistogramTester histogram_tester;
  1806. worker()->UpdateWithGarbageCollection(std::move(updates1),
  1807. garbage_collection_directive);
  1808. ASSERT_EQ(1, bridge()->merge_call_count());
  1809. // The duration should get recorded.
  1810. histogram_tester.ExpectTotalCount(
  1811. "Sync.ModelTypeConfigurationTime.Ephemeral.PREFERENCE",
  1812. /*count=*/1);
  1813. }
  1814. {
  1815. UpdateResponseDataList updates2;
  1816. updates2.push_back(worker()->GenerateUpdateData(
  1817. ClientTagHash(), GeneratePrefSpecifics(kKey1, kValue1), 1, "k1"));
  1818. base::HistogramTester histogram_tester;
  1819. // Send one more update with the same data.
  1820. worker()->UpdateWithGarbageCollection(std::move(updates2),
  1821. garbage_collection_directive);
  1822. ASSERT_EQ(2, bridge()->merge_call_count());
  1823. // The duration should not get recorded again.
  1824. histogram_tester.ExpectTotalCount(
  1825. "Sync.ModelTypeConfigurationTime.Ephemeral.PREFERENCE",
  1826. /*count=*/0);
  1827. }
  1828. }
  1829. // Tests that the processor reports an error for updates without a version GC
  1830. // directive that are received for types that don't support incremental updates.
  1831. TEST_F(FullUpdateClientTagBasedModelTypeProcessorTest,
  1832. ShouldReportErrorForUnsupportedIncrementalUpdate) {
  1833. InitializeToReadyState();
  1834. ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite::
  1835. kSupportsIncrementalUpdatesMismatch);
  1836. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1837. GeneratePrefSpecifics(kKey1, kValue1));
  1838. }
  1839. // Tests that empty updates without a version GC are processed for types that
  1840. // don't support incremental updates. The only outcome if these updates should
  1841. // be storing an updated progress marker.
  1842. TEST_F(FullUpdateClientTagBasedModelTypeProcessorTest,
  1843. ShouldProcessEmptyUpdate) {
  1844. // Override the initial progress marker token so that we can check it gets
  1845. // changed.
  1846. sync_pb::ModelTypeState initial_model_type_state(db()->model_type_state());
  1847. initial_model_type_state.mutable_progress_marker()->set_token("OLD");
  1848. db()->set_model_type_state(initial_model_type_state);
  1849. InitializeToReadyState();
  1850. sync_pb::ModelTypeState new_model_type_state(db()->model_type_state());
  1851. new_model_type_state.mutable_progress_marker()->set_token("NEW");
  1852. worker()->UpdateModelTypeState(new_model_type_state);
  1853. worker()->UpdateFromServer(UpdateResponseDataList());
  1854. // Verify that the empty update was correctly passed into the bridge and that
  1855. // it stored the updated progress marker.
  1856. EXPECT_EQ(0, bridge()->merge_call_count());
  1857. EXPECT_EQ(1, bridge()->apply_call_count());
  1858. EXPECT_EQ("NEW", db()->model_type_state().progress_marker().token());
  1859. }
  1860. // Tests that the processor correctly handles an initial (non-empty) update
  1861. // without any gc directives (as it happens in the migration to USS).
  1862. TEST_F(FullUpdateClientTagBasedModelTypeProcessorTest,
  1863. ShouldProcessInitialUpdate) {
  1864. // Do not set any model type state to emulate that initial sync has not been
  1865. // done yet.
  1866. ModelReadyToSync();
  1867. OnSyncStarting();
  1868. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1869. GeneratePrefSpecifics(kKey1, kValue1));
  1870. }
  1871. // Tests that a real local change wins over a remote encryption-only change.
  1872. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldIgnoreRemoteEncryption) {
  1873. InitializeToReadyState();
  1874. EntitySpecifics specifics1 = WriteItemAndAck(kKey1, kValue1);
  1875. EntitySpecifics specifics2 = WritePrefItem(bridge(), kKey1, kValue2);
  1876. UpdateResponseDataList update;
  1877. update.push_back(
  1878. worker()->GenerateUpdateData(GetPrefHash(kKey1), specifics1, 1, "k1"));
  1879. worker()->UpdateWithEncryptionKey("k1", std::move(update));
  1880. OnCommitDataLoaded();
  1881. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  1882. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1)}, {specifics2});
  1883. }
  1884. // Same as above but with two commit requests before one ack.
  1885. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1886. ShouldIgnoreRemoteEncryptionInterleaved) {
  1887. InitializeToReadyState();
  1888. // WriteAndAck entity to get id from the server.
  1889. WriteItemAndAck(kKey1, kValue1);
  1890. EntitySpecifics specifics1 = WritePrefItem(bridge(), kKey1, kValue2);
  1891. EntitySpecifics specifics2 = WritePrefItem(bridge(), kKey1, kValue3);
  1892. worker()->AckOnePendingCommit();
  1893. // kValue2 is now the base value.
  1894. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
  1895. worker()->VerifyNthPendingCommit(0, {GetPrefHash(kKey1)}, {specifics2});
  1896. UpdateResponseDataList update;
  1897. update.push_back(
  1898. worker()->GenerateUpdateData(GetPrefHash(kKey1), specifics1, 1, "k1"));
  1899. worker()->UpdateWithEncryptionKey("k1", std::move(update));
  1900. OnCommitDataLoaded();
  1901. EXPECT_EQ(2U, worker()->GetNumPendingCommits());
  1902. worker()->VerifyNthPendingCommit(1, {GetPrefHash(kKey1)}, {specifics2});
  1903. }
  1904. // Tests that UpdateStorageKey propagates storage key to ProcessorEntity
  1905. // and updates corresponding entity's metadata in MetadataChangeList, and
  1906. // UntrackEntity will remove corresponding ProcessorEntity and do not add
  1907. // any entity's metadata into MetadataChangeList.
  1908. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldUpdateStorageKey) {
  1909. // Setup bridge to not support calls to GetStorageKey. This will cause
  1910. // FakeModelTypeSyncBridge to call UpdateStorageKey for new entities and will
  1911. // DCHECK if GetStorageKey gets called.
  1912. bridge()->SetSupportsGetStorageKey(false);
  1913. ModelReadyToSync();
  1914. OnSyncStarting();
  1915. // Initial update from server should be handled by MergeSyncData.
  1916. UpdateResponseDataList updates;
  1917. updates.push_back(worker()->GenerateUpdateData(
  1918. GetPrefHash(kKey1), GeneratePrefSpecifics(kKey1, kValue1)));
  1919. // Create update which will be ignored by bridge.
  1920. updates.push_back(worker()->GenerateUpdateData(
  1921. GetPrefHash(kKey3), GeneratePrefSpecifics(kKey3, kValue3)));
  1922. bridge()->AddPrefValueToIgnore(kValue3);
  1923. worker()->UpdateFromServer(std::move(updates));
  1924. EXPECT_EQ(1, bridge()->merge_call_count());
  1925. EXPECT_EQ(1U, ProcessorEntityCount());
  1926. // Metadata should be written under a new storage key. This means that
  1927. // UpdateStorageKey was called and value of storage key got propagated to
  1928. // MetadataChangeList.
  1929. const std::string storage_key1 = bridge()->GetLastGeneratedStorageKey();
  1930. EXPECT_TRUE(db()->HasMetadata(storage_key1));
  1931. EXPECT_EQ(1U, db()->metadata_count());
  1932. EXPECT_EQ(0, bridge()->get_storage_key_call_count());
  1933. // Local update should affect the same entity. This ensures that storage key
  1934. // to client tag hash mapping was updated on the previous step.
  1935. WritePrefItem(bridge(), storage_key1, kValue2);
  1936. EXPECT_EQ(1U, ProcessorEntityCount());
  1937. EXPECT_EQ(1U, db()->metadata_count());
  1938. // Second update from server should be handled by ApplySyncChanges. Similarly
  1939. // It should call UpdateStorageKey, not GetStorageKey.
  1940. worker()->UpdateFromServer(GetPrefHash(kKey2),
  1941. GeneratePrefSpecifics(kKey2, kValue2));
  1942. EXPECT_EQ(1, bridge()->apply_call_count());
  1943. const std::string storage_key2 = bridge()->GetLastGeneratedStorageKey();
  1944. EXPECT_NE(storage_key1, storage_key2);
  1945. EXPECT_TRUE(db()->HasMetadata(storage_key2));
  1946. EXPECT_EQ(2U, db()->metadata_count());
  1947. EXPECT_EQ(0, bridge()->get_storage_key_call_count());
  1948. }
  1949. // Tests that reencryption scenario works correctly for types that don't support
  1950. // GetStorageKey(). When update from server delivers updated encryption key, all
  1951. // entities should be reencrypted including new entity that just got received
  1952. // from server.
  1953. TEST_F(ClientTagBasedModelTypeProcessorTest,
  1954. ShouldReencryptDatatypeWithoutStorageKeySupport) {
  1955. bridge()->SetSupportsGetStorageKey(false);
  1956. InitializeToReadyState();
  1957. UpdateResponseDataList update;
  1958. update.push_back(worker()->GenerateUpdateData(
  1959. GetPrefHash(kKey1), GeneratePrefSpecifics(kKey1, kValue1), 1, "ek1"));
  1960. worker()->UpdateWithEncryptionKey("ek2", std::move(update));
  1961. OnCommitDataLoaded();
  1962. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1963. }
  1964. // Tests that UntrackEntity won't propagate storage key to
  1965. // ProcessorEntity, and no entity's metadata are added into
  1966. // MetadataChangeList.
  1967. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldUntrackEntity) {
  1968. // Setup bridge to not support calls to GetStorageKey. This will cause
  1969. // FakeModelTypeSyncBridge to call UpdateStorageKey for new entities and will
  1970. // DCHECK if GetStorageKey gets called.
  1971. bridge()->SetSupportsGetStorageKey(false);
  1972. bridge()->AddPrefValueToIgnore(kValue1);
  1973. ModelReadyToSync();
  1974. OnSyncStarting();
  1975. // Initial update from server should be handled by MergeSyncData.
  1976. worker()->UpdateFromServer(GetPrefHash(kKey1),
  1977. GeneratePrefSpecifics(kKey1, kValue1));
  1978. EXPECT_EQ(1, bridge()->merge_call_count());
  1979. EXPECT_EQ(0U, ProcessorEntityCount());
  1980. // Metadata should not be written under kUntrackKey1. This means that
  1981. // UntrackEntity was called and corresponding ProcessorEntity is
  1982. // removed and no storage key got propagated to MetadataChangeList.
  1983. EXPECT_FALSE(db()->HasMetadata(kKey1));
  1984. EXPECT_EQ(0U, db()->metadata_count());
  1985. EXPECT_EQ(0, bridge()->get_storage_key_call_count());
  1986. }
  1987. // Tests that UntrackEntityForStorage won't propagate storage key to
  1988. // ProcessorEntity, and no entity's metadata are added into
  1989. // MetadataChangeList.
  1990. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldUntrackEntityForStorageKey) {
  1991. InitializeToReadyState();
  1992. WritePrefItem(bridge(), kKey1, kValue1);
  1993. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  1994. worker()->AckOnePendingCommit();
  1995. // Check the processor tracks the entity.
  1996. TypeEntitiesCount count(GetModelType());
  1997. type_processor()->GetTypeEntitiesCountForDebugging(
  1998. base::BindOnce(&CaptureTypeEntitiesCount, &count));
  1999. ASSERT_EQ(1, count.non_tombstone_entities);
  2000. ASSERT_NE(nullptr, GetEntityForStorageKey(kKey1));
  2001. // The bridge deletes the data locally and does not want to sync the deletion.
  2002. // It only untracks the entity.
  2003. type_processor()->UntrackEntityForStorageKey(kKey1);
  2004. // The deletion is not synced up.
  2005. worker()->VerifyPendingCommits({});
  2006. // The processor tracks no entity any more.
  2007. type_processor()->GetTypeEntitiesCountForDebugging(
  2008. base::BindOnce(&CaptureTypeEntitiesCount, &count));
  2009. EXPECT_EQ(0, count.non_tombstone_entities);
  2010. EXPECT_EQ(nullptr, GetEntityForStorageKey(kKey1));
  2011. }
  2012. // Tests that UntrackEntityForStorage does not crash if no such entity is being
  2013. // tracked.
  2014. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2015. ShouldIgnoreUntrackEntityForInexistentStorageKey) {
  2016. InitializeToReadyState();
  2017. // This should not crash for an unknown storage key and simply ignore the
  2018. // call.
  2019. type_processor()->UntrackEntityForStorageKey(kKey1);
  2020. // No deletion is not synced up.
  2021. worker()->VerifyPendingCommits({});
  2022. // The processor tracks no entity.
  2023. TypeEntitiesCount count(GetModelType());
  2024. type_processor()->GetTypeEntitiesCountForDebugging(
  2025. base::BindOnce(&CaptureTypeEntitiesCount, &count));
  2026. EXPECT_EQ(0, count.non_tombstone_entities);
  2027. EXPECT_EQ(nullptr, GetEntityForStorageKey(kKey1));
  2028. }
  2029. // Tests that UntrackEntityForClientTagHash won't propagate storage key to
  2030. // ProcessorEntity, and no entity's metadata are added into MetadataChangeList.
  2031. // This test is pretty same as ShouldUntrackEntityForStorageKey.
  2032. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2033. ShouldUntrackEntityForClientTagHash) {
  2034. InitializeToReadyState();
  2035. WritePrefItem(bridge(), kKey1, kValue1);
  2036. worker()->VerifyPendingCommits({{GetPrefHash(kKey1)}});
  2037. worker()->AckOnePendingCommit();
  2038. // Check the processor tracks the entity.
  2039. TypeEntitiesCount count(GetModelType());
  2040. type_processor()->GetTypeEntitiesCountForDebugging(
  2041. base::BindOnce(&CaptureTypeEntitiesCount, &count));
  2042. ASSERT_EQ(1, count.non_tombstone_entities);
  2043. ASSERT_NE(nullptr, GetEntityForStorageKey(kKey1));
  2044. // The bridge deletes the data locally and does not want to sync the deletion.
  2045. // It only untracks the entity.
  2046. type_processor()->UntrackEntityForClientTagHash(GetPrefHash(kKey1));
  2047. // The deletion is not synced up.
  2048. worker()->VerifyPendingCommits({});
  2049. // The processor tracks no entity any more.
  2050. type_processor()->GetTypeEntitiesCountForDebugging(
  2051. base::BindOnce(&CaptureTypeEntitiesCount, &count));
  2052. EXPECT_EQ(0, count.non_tombstone_entities);
  2053. EXPECT_EQ(nullptr, GetEntityForStorageKey(kKey1));
  2054. }
  2055. // Tests that the processor reports an error for updates with a version GC
  2056. // directive that are received for types that support incremental updates.
  2057. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2058. ShouldNotApplyGarbageCollectionByVersion) {
  2059. InitializeToReadyState();
  2060. ExpectError(ClientTagBasedModelTypeProcessor::ErrorSite::
  2061. kSupportsIncrementalUpdatesMismatch);
  2062. sync_pb::GarbageCollectionDirective garbage_collection_directive;
  2063. garbage_collection_directive.set_version_watermark(2);
  2064. worker()->UpdateWithGarbageCollection(garbage_collection_directive);
  2065. }
  2066. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2067. ShouldDeleteMetadataWhenCacheGuidMismatch) {
  2068. // Commit item.
  2069. InitializeToReadyState();
  2070. WriteItemAndAck(kKey1, kValue1);
  2071. // Reset the processor to simulate a restart.
  2072. ResetState(/*keep_db=*/true);
  2073. // A new processor loads the metadata after changing the cache GUID.
  2074. bridge()->SetInitialSyncDone(true);
  2075. std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch();
  2076. sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState());
  2077. model_type_state.set_cache_guid("WRONG_CACHE_GUID");
  2078. metadata_batch->SetModelTypeState(model_type_state);
  2079. type_processor()->ModelReadyToSync(std::move(metadata_batch));
  2080. ASSERT_TRUE(type_processor()->IsModelReadyToSyncForTest());
  2081. OnSyncStarting("DefaultAuthenticatedAccountId", "TestCacheGuid");
  2082. // Model should still be ready to sync.
  2083. ASSERT_TRUE(type_processor()->IsModelReadyToSyncForTest());
  2084. // OnSyncStarting() should have completed.
  2085. EXPECT_NE(nullptr, worker());
  2086. // Upon a mismatch, metadata should have been cleared.
  2087. EXPECT_EQ(0U, db()->metadata_count());
  2088. EXPECT_FALSE(type_processor()->IsTrackingMetadata());
  2089. // Initial update.
  2090. worker()->UpdateFromServer();
  2091. EXPECT_TRUE(type_processor()->IsTrackingMetadata());
  2092. EXPECT_EQ("TestCacheGuid", type_processor()->TrackedCacheGuid());
  2093. }
  2094. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2095. ShouldDeleteMetadataWhenDataTypeIdMismatch) {
  2096. // Commit item.
  2097. InitializeToReadyState();
  2098. WriteItemAndAck(kKey1, kValue1);
  2099. // Reset the processor to simulate a restart.
  2100. ResetState(/*keep_db=*/true);
  2101. // A new processor loads the metadata after changing the data type id.
  2102. bridge()->SetInitialSyncDone(true);
  2103. std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch();
  2104. sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState());
  2105. // This processor is supposed to process Preferences. Mark the model type
  2106. // state to be for sessions to simulate a data type id mismatch.
  2107. model_type_state.mutable_progress_marker()->set_data_type_id(
  2108. GetSpecificsFieldNumberFromModelType(SESSIONS));
  2109. metadata_batch->SetModelTypeState(model_type_state);
  2110. type_processor()->ModelReadyToSync(std::move(metadata_batch));
  2111. ASSERT_TRUE(type_processor()->IsModelReadyToSyncForTest());
  2112. OnSyncStarting();
  2113. // Model should still be ready to sync.
  2114. ASSERT_TRUE(type_processor()->IsModelReadyToSyncForTest());
  2115. // OnSyncStarting() should have completed.
  2116. EXPECT_NE(nullptr, worker());
  2117. // Upon a mismatch, metadata should have been cleared.
  2118. EXPECT_EQ(0U, db()->metadata_count());
  2119. }
  2120. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2121. ShouldClearOrphanMetadataInGetLocalChangesWhenDataIsMissing) {
  2122. InitializeToReadyState();
  2123. WritePrefItem(bridge(), kKey1, kValue1);
  2124. // Loose the entity in the bridge (keeping the metadata around as an orphan).
  2125. bridge()->MimicBugToLooseItemWithoutNotifyingProcessor(kKey1);
  2126. ASSERT_FALSE(db()->HasData(kKey1));
  2127. ASSERT_TRUE(db()->HasMetadata(kKey1));
  2128. ASSERT_NE(nullptr, GetEntityForStorageKey(kKey1));
  2129. // Reset "the browser" so that the processor looses the copy of the data.
  2130. ResetState(/*keep_db=*/true);
  2131. // Initializing the processor will trigger it to commit again. It does not
  2132. // have a copy of the data so it will ask the bridge.
  2133. {
  2134. base::HistogramTester histogram_tester;
  2135. bridge()->ExpectSynchronousDataCallback();
  2136. InitializeToReadyState();
  2137. histogram_tester.ExpectBucketCount(
  2138. "Sync.ModelTypeOrphanMetadata.GetData",
  2139. /*bucket=*/ModelTypeHistogramValue(GetModelType()), /*count=*/1);
  2140. }
  2141. // Orphan metadata should have been deleted.
  2142. EXPECT_EQ(1, bridge()->apply_call_count());
  2143. EXPECT_FALSE(db()->HasMetadata(kKey1));
  2144. EXPECT_EQ(nullptr, GetEntityForStorageKey(kKey1));
  2145. base::HistogramTester histogram_tester;
  2146. // Do it again, explicitly. The processor does not track the entity so it
  2147. // shouldn't ask the bridge or return local changes.
  2148. CommitRequestDataList commit_request;
  2149. type_processor()->GetLocalChanges(
  2150. INT_MAX, base::BindOnce(&CaptureCommitRequest, &commit_request));
  2151. EXPECT_EQ(0U, commit_request.size());
  2152. EXPECT_TRUE(bridge()->GetDataCallback().is_null());
  2153. // The processor should not report orphan again in UMA.
  2154. histogram_tester.ExpectBucketCount(
  2155. "Sync.ModelTypeOrphanMetadata.GetData",
  2156. /*bucket=*/ModelTypeHistogramValue(GetModelType()), /*count=*/0);
  2157. }
  2158. TEST_F(
  2159. ClientTagBasedModelTypeProcessorTest,
  2160. ShouldNotReportOrphanMetadataInGetLocalChangesWhenDataIsAlreadyUntracked) {
  2161. InitializeToReadyState();
  2162. WritePrefItem(bridge(), kKey1, kValue1);
  2163. // Loose the entity in the bridge (keeping the metadata around as an orphan).
  2164. bridge()->MimicBugToLooseItemWithoutNotifyingProcessor(kKey1);
  2165. ASSERT_FALSE(db()->HasData(kKey1));
  2166. ASSERT_TRUE(db()->HasMetadata(kKey1));
  2167. ASSERT_NE(nullptr, GetEntityForStorageKey(kKey1));
  2168. // Reset "the browser" so that the processor looses the copy of the data.
  2169. ResetState(/*keep_db=*/true);
  2170. // Initializing the processor will trigger it to commit again. It does not
  2171. // have a copy of the data so it will ask the bridge.
  2172. base::HistogramTester histogram_tester;
  2173. InitializeToReadyState();
  2174. // The bridge has not passed the data back to the processor, we untrack the
  2175. // entity.
  2176. type_processor()->UntrackEntityForStorageKey(kKey1);
  2177. // Make the bridge pass the data back to the processor. Because the entity is
  2178. // already deleted in the processor, no further orphan gets reported.
  2179. std::move(bridge()->GetDataCallback()).Run();
  2180. histogram_tester.ExpectTotalCount("Sync.ModelTypeOrphanMetadata.GetData",
  2181. /*count=*/0);
  2182. EXPECT_EQ(0, bridge()->apply_call_count());
  2183. EXPECT_EQ(nullptr, GetEntityForStorageKey(kKey1));
  2184. // The expectation below documents the fact that bridges are responsible for
  2185. // clearing the untracked metadata from their databases.
  2186. EXPECT_TRUE(db()->HasMetadata(kKey1));
  2187. }
  2188. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2189. ShouldNotReportOrphanMetadataInGetLocalChangesWhenDataIsAlreadyDeleted) {
  2190. InitializeToReadyState();
  2191. WritePrefItem(bridge(), kKey1, kValue1);
  2192. // Loose the entity in the bridge (keeping the metadata around as an orphan).
  2193. bridge()->MimicBugToLooseItemWithoutNotifyingProcessor(kKey1);
  2194. ASSERT_FALSE(db()->HasData(kKey1));
  2195. ASSERT_TRUE(db()->HasMetadata(kKey1));
  2196. ASSERT_NE(nullptr, GetEntityForStorageKey(kKey1));
  2197. // Reset "the browser" so that the processor looses the copy of the data.
  2198. ResetState(/*keep_db=*/true);
  2199. // Initializing the processor will trigger it to commit again. It does not
  2200. // have a copy of the data so it will ask the bridge.
  2201. base::HistogramTester histogram_tester;
  2202. InitializeToReadyState();
  2203. // The bridge has not passed the data back to the processor, we delete the
  2204. // entity.
  2205. bridge()->DeleteItem(kKey1);
  2206. // Make the bridge pass the data back to the processor. Because the entity is
  2207. // already deleted in the processor, no further orphan gets reported.
  2208. std::move(bridge()->GetDataCallback()).Run();
  2209. histogram_tester.ExpectTotalCount("Sync.ModelTypeOrphanMetadata.GetData",
  2210. /*count=*/0);
  2211. EXPECT_EQ(0, bridge()->apply_call_count());
  2212. EXPECT_EQ(nullptr, GetEntityForStorageKey(kKey1));
  2213. }
  2214. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2215. ShouldNotReportOrphanMetadataInGetLocalChangesWhenDataIsPresent) {
  2216. InitializeToReadyState();
  2217. WritePrefItem(bridge(), kKey1, kValue1);
  2218. ASSERT_TRUE(db()->HasData(kKey1));
  2219. ASSERT_TRUE(db()->HasMetadata(kKey1));
  2220. ASSERT_NE(nullptr, GetEntityForStorageKey(kKey1));
  2221. // Reset "the browser" so that the processor looses the copy of the data.
  2222. ResetState(/*keep_db=*/true);
  2223. // Initializing the processor will trigger it to commit again. It does not
  2224. // have a copy of the data so it will ask the bridge.
  2225. base::HistogramTester histogram_tester;
  2226. bridge()->ExpectSynchronousDataCallback();
  2227. InitializeToReadyState();
  2228. // Now everything is committed and GetLocalChanges is empty again.
  2229. CommitRequestDataList commit_request;
  2230. type_processor()->GetLocalChanges(
  2231. INT_MAX, base::BindOnce(&CaptureCommitRequest, &commit_request));
  2232. EXPECT_EQ(0U, commit_request.size());
  2233. // The processor never reports any orphan.
  2234. histogram_tester.ExpectTotalCount("Sync.ModelTypeOrphanMetadata.GetData",
  2235. /*count=*/0);
  2236. EXPECT_TRUE(db()->HasData(kKey1));
  2237. EXPECT_TRUE(db()->HasMetadata(kKey1));
  2238. EXPECT_NE(nullptr, GetEntityForStorageKey(kKey1));
  2239. }
  2240. // This tests the case when the bridge deletes an item, and before it's
  2241. // committed to the server, it created again with a different storage key.
  2242. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2243. ShouldDeleteItemAndRecreaeItWithDifferentStorageKey) {
  2244. const std::string kStorageKey1 = "StorageKey1";
  2245. const std::string kStorageKey2 = "StorageKey2";
  2246. // This verifies that the processor doesn't use GetStorageKey() method.
  2247. bridge()->SetSupportsGetStorageKey(false);
  2248. InitializeToReadyState();
  2249. std::unique_ptr<EntityData> entity_data1 =
  2250. GeneratePrefEntityData(kKey1, kValue1);
  2251. bridge()->WriteItem(kStorageKey1, std::move(entity_data1));
  2252. worker()->AckOnePendingCommit();
  2253. EXPECT_TRUE(type_processor()->IsTrackingEntityForTest(kStorageKey1));
  2254. // Delete the data associated with the first storage key.
  2255. bridge()->DeleteItem(kStorageKey1);
  2256. // // Add the same data under a different storage key.
  2257. std::unique_ptr<EntityData> entity_data2 =
  2258. GeneratePrefEntityData(kKey1, kValue1);
  2259. bridge()->WriteItem(kStorageKey2, std::move(entity_data2));
  2260. EXPECT_FALSE(type_processor()->IsTrackingEntityForTest(kStorageKey1));
  2261. EXPECT_FALSE(db()->HasMetadata(kStorageKey1));
  2262. EXPECT_TRUE(type_processor()->IsTrackingEntityForTest(kStorageKey2));
  2263. }
  2264. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2265. ShouldPropagateFailedCommitItemsToBridgeWhenCommitCompleted) {
  2266. InitializeToReadyState();
  2267. FailedCommitResponseData response_data;
  2268. response_data.client_tag_hash = GetPrefHash("dummy tag");
  2269. response_data.response_type = sync_pb::CommitResponse::TRANSIENT_ERROR;
  2270. response_data.datatype_specific_error.mutable_sharing_message_error()
  2271. ->set_error_code(sync_pb::SharingMessageCommitError::INVALID_ARGUMENT);
  2272. FailedCommitResponseDataList failed_list;
  2273. failed_list.push_back(response_data);
  2274. FailedCommitResponseDataList actual_error_response_list;
  2275. auto on_commit_attempt_errors_callback = base::BindOnce(
  2276. [](FailedCommitResponseDataList* actual_error_response_list,
  2277. const FailedCommitResponseDataList& error_response_list) {
  2278. // We put expectations outside of the callback, so that they fail if
  2279. // callback is not ran.
  2280. *actual_error_response_list = error_response_list;
  2281. },
  2282. &actual_error_response_list);
  2283. bridge()->SetOnCommitAttemptErrorsCallback(
  2284. std::move(on_commit_attempt_errors_callback));
  2285. type_processor()->OnCommitCompleted(
  2286. model_type_state(),
  2287. /*committed_response_list=*/CommitResponseDataList(), failed_list);
  2288. ASSERT_EQ(1u, actual_error_response_list.size());
  2289. EXPECT_EQ(0, bridge()->commit_failures_count());
  2290. EXPECT_EQ(response_data.client_tag_hash,
  2291. actual_error_response_list[0].client_tag_hash);
  2292. EXPECT_EQ(response_data.response_type,
  2293. actual_error_response_list[0].response_type);
  2294. EXPECT_EQ(response_data.datatype_specific_error.sharing_message_error()
  2295. .error_code(),
  2296. actual_error_response_list[0]
  2297. .datatype_specific_error.sharing_message_error()
  2298. .error_code());
  2299. }
  2300. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2301. ShouldNotPropagateFailedCommitAttemptToBridgeWhenNoFailedItems) {
  2302. InitializeToReadyState();
  2303. auto on_commit_attempt_errors_callback = base::BindOnce(
  2304. [](const FailedCommitResponseDataList& error_response_list) {
  2305. ADD_FAILURE()
  2306. << "OnCommitAttemptErrors is called when no failed items.";
  2307. });
  2308. bridge()->SetOnCommitAttemptErrorsCallback(
  2309. std::move(on_commit_attempt_errors_callback));
  2310. type_processor()->OnCommitCompleted(
  2311. model_type_state(),
  2312. /*committed_response_list=*/CommitResponseDataList(),
  2313. /*error_response_list=*/FailedCommitResponseDataList());
  2314. EXPECT_EQ(0, bridge()->commit_failures_count());
  2315. }
  2316. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldPropagateFullCommitFailure) {
  2317. InitializeToReadyState();
  2318. ASSERT_EQ(0, bridge()->commit_failures_count());
  2319. type_processor()->OnCommitFailed(syncer::SyncCommitError::kNetworkError);
  2320. EXPECT_EQ(1, bridge()->commit_failures_count());
  2321. }
  2322. class CommitOnlyClientTagBasedModelTypeProcessorTest
  2323. : public ClientTagBasedModelTypeProcessorTest {
  2324. protected:
  2325. ModelType GetModelType() override {
  2326. DCHECK(CommitOnlyTypes().Has(USER_EVENTS));
  2327. return USER_EVENTS;
  2328. }
  2329. };
  2330. TEST_F(CommitOnlyClientTagBasedModelTypeProcessorTest,
  2331. ShouldExposeNewlyTrackedAccountId) {
  2332. ModelReadyToSync();
  2333. ASSERT_EQ("", type_processor()->TrackedAccountId());
  2334. OnSyncStarting();
  2335. EXPECT_EQ(kDefaultAuthenticatedAccountId,
  2336. type_processor()->TrackedAccountId());
  2337. }
  2338. TEST_F(CommitOnlyClientTagBasedModelTypeProcessorTest,
  2339. ShouldExposePreviouslyTrackedAccountId) {
  2340. std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch();
  2341. sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState());
  2342. model_type_state.set_initial_sync_done(true);
  2343. model_type_state.set_cache_guid(kCacheGuid);
  2344. model_type_state.set_authenticated_account_id("PersistedAccountId");
  2345. model_type_state.mutable_progress_marker()->set_data_type_id(
  2346. GetSpecificsFieldNumberFromModelType(GetModelType()));
  2347. metadata_batch->SetModelTypeState(model_type_state);
  2348. type_processor()->ModelReadyToSync(std::move(metadata_batch));
  2349. // Even prior to starting sync, the account ID should already be tracked.
  2350. EXPECT_EQ("PersistedAccountId", type_processor()->TrackedAccountId());
  2351. // If sync gets started, the account should still be tracked.
  2352. OnSyncStarting("PersistedAccountId");
  2353. EXPECT_EQ("PersistedAccountId", type_processor()->TrackedAccountId());
  2354. }
  2355. TEST_F(CommitOnlyClientTagBasedModelTypeProcessorTest,
  2356. ShouldCallMergeWhenSyncEnabled) {
  2357. ModelReadyToSync();
  2358. ASSERT_EQ("", type_processor()->TrackedAccountId());
  2359. ASSERT_EQ(0, bridge()->merge_call_count());
  2360. OnSyncStarting();
  2361. EXPECT_EQ(1, bridge()->merge_call_count());
  2362. }
  2363. TEST_F(CommitOnlyClientTagBasedModelTypeProcessorTest,
  2364. ShouldNotCallMergeAfterRestart) {
  2365. std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch();
  2366. sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState());
  2367. model_type_state.set_initial_sync_done(true);
  2368. model_type_state.set_cache_guid(kCacheGuid);
  2369. model_type_state.set_authenticated_account_id("PersistedAccountId");
  2370. model_type_state.mutable_progress_marker()->set_data_type_id(
  2371. GetSpecificsFieldNumberFromModelType(GetModelType()));
  2372. metadata_batch->SetModelTypeState(model_type_state);
  2373. type_processor()->ModelReadyToSync(std::move(metadata_batch));
  2374. // Even prior to starting sync, the account ID should already be tracked.
  2375. ASSERT_EQ("PersistedAccountId", type_processor()->TrackedAccountId());
  2376. // When sync gets started, MergeSyncData() should not be called.
  2377. OnSyncStarting("PersistedAccountId");
  2378. ASSERT_EQ(0, bridge()->merge_call_count());
  2379. }
  2380. // Test that commit only types are deleted after commit response.
  2381. TEST_F(CommitOnlyClientTagBasedModelTypeProcessorTest,
  2382. DISABLED_ShouldCommitAndDeleteWhenAcked) {
  2383. InitializeToReadyState();
  2384. EXPECT_TRUE(db()->model_type_state().initial_sync_done());
  2385. const uint64_t key1 = 1234;
  2386. const std::string key1s = base::NumberToString(key1);
  2387. WriteUserEventItem(bridge(), key1, 4321);
  2388. worker()->VerifyPendingCommits({{GetHash(USER_EVENTS, key1s)}});
  2389. EXPECT_EQ(1U, db()->data_count());
  2390. EXPECT_EQ(1U, db()->metadata_count());
  2391. worker()->AckOnePendingCommit();
  2392. EXPECT_EQ(0U, db()->data_count());
  2393. EXPECT_EQ(0U, db()->metadata_count());
  2394. }
  2395. // Test that commit only types maintain tracking of entities while unsynced
  2396. // changes exist.
  2397. TEST_F(CommitOnlyClientTagBasedModelTypeProcessorTest,
  2398. ShouldTrackUnsyncedChangesAfterPartialCommit) {
  2399. InitializeToReadyState();
  2400. const uint64_t key1 = 1234;
  2401. const uint64_t key2 = 2345;
  2402. const std::string key1s = base::NumberToString(key1);
  2403. const std::string key2s = base::NumberToString(key2);
  2404. WriteUserEventItem(bridge(), key1, 4321);
  2405. worker()->VerifyPendingCommits({{GetHash(USER_EVENTS, key1s)}});
  2406. EXPECT_EQ(1U, db()->data_count());
  2407. EXPECT_EQ(1U, db()->metadata_count());
  2408. WriteUserEventItem(bridge(), key1, 5432);
  2409. worker()->VerifyPendingCommits(
  2410. {{GetHash(USER_EVENTS, key1s)}, {GetHash(USER_EVENTS, key1s)}});
  2411. EXPECT_EQ(1U, db()->data_count());
  2412. EXPECT_EQ(1U, db()->metadata_count());
  2413. worker()->AckOnePendingCommit();
  2414. worker()->VerifyPendingCommits({{GetHash(USER_EVENTS, key1s)}});
  2415. EXPECT_EQ(1U, db()->data_count());
  2416. EXPECT_EQ(1U, db()->metadata_count());
  2417. // The version field isn't meaningful on commit only types, so force a value
  2418. // that isn't incremented to verify everything still works.
  2419. worker()->AckOnePendingCommit(0 /* version_offset */);
  2420. worker()->VerifyPendingCommits({});
  2421. EXPECT_EQ(0U, db()->data_count());
  2422. EXPECT_EQ(0U, db()->metadata_count());
  2423. }
  2424. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldResetOnInvalidCacheGuid) {
  2425. ResetStateWriteItem(kKey1, kValue1);
  2426. InitializeToMetadataLoaded();
  2427. OnSyncStarting();
  2428. OnCommitDataLoaded();
  2429. ASSERT_EQ(1U, ProcessorEntityCount());
  2430. ResetStateWriteItem(kKey1, kValue1);
  2431. sync_pb::ModelTypeState model_type_state = db()->model_type_state();
  2432. model_type_state.set_cache_guid("OtherCacheGuid");
  2433. db()->set_model_type_state(model_type_state);
  2434. ModelReadyToSync();
  2435. OnSyncStarting();
  2436. EXPECT_EQ(0U, ProcessorEntityCount());
  2437. }
  2438. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldResetOnInvalidDataTypeId) {
  2439. ResetStateWriteItem(kKey1, kValue1);
  2440. ASSERT_EQ(0U, ProcessorEntityCount());
  2441. // Initialize change processor, expect to load data from the bridge.
  2442. InitializeToMetadataLoaded();
  2443. OnSyncStarting();
  2444. OnCommitDataLoaded();
  2445. ASSERT_EQ(1U, ProcessorEntityCount());
  2446. ResetStateWriteItem(kKey1, kValue1);
  2447. OnSyncStarting();
  2448. // Set different data type id.
  2449. sync_pb::ModelTypeState model_type_state = db()->model_type_state();
  2450. ASSERT_NE(model_type_state.progress_marker().data_type_id(),
  2451. GetSpecificsFieldNumberFromModelType(AUTOFILL));
  2452. model_type_state.mutable_progress_marker()->set_data_type_id(
  2453. GetSpecificsFieldNumberFromModelType(AUTOFILL));
  2454. db()->set_model_type_state(model_type_state);
  2455. ModelReadyToSync();
  2456. EXPECT_EQ(0U, ProcessorEntityCount());
  2457. }
  2458. TEST_F(ClientTagBasedModelTypeProcessorTest,
  2459. ShouldResetForDuplicateClientTagHash) {
  2460. base::HistogramTester histogram_tester;
  2461. const syncer::ClientTagHash kClientTagHash =
  2462. ClientTagHash::FromUnhashed(AUTOFILL, "tag");
  2463. sync_pb::EntityMetadata entity_metadata1;
  2464. entity_metadata1.set_client_tag_hash(kClientTagHash.value());
  2465. entity_metadata1.set_creation_time(0);
  2466. sync_pb::EntityMetadata entity_metadata2;
  2467. entity_metadata2.set_client_tag_hash(kClientTagHash.value());
  2468. entity_metadata2.set_creation_time(0);
  2469. sync_pb::EntityMetadata entity_metadata3;
  2470. entity_metadata3.set_client_tag_hash(kClientTagHash.value());
  2471. entity_metadata3.set_creation_time(0);
  2472. db()->PutMetadata(kKey1, std::move(entity_metadata1));
  2473. db()->PutMetadata(kKey2, std::move(entity_metadata2));
  2474. db()->PutMetadata(kKey3, std::move(entity_metadata3));
  2475. InitializeToReadyState();
  2476. // With a client tag hash duplicate, metadata should have been cleared.
  2477. EXPECT_EQ(0U, db()->metadata_count());
  2478. EXPECT_EQ(0U, ProcessorEntityCount());
  2479. EXPECT_FALSE(type_processor()->IsTrackingMetadata());
  2480. // Initial update.
  2481. worker()->UpdateFromServer();
  2482. EXPECT_TRUE(type_processor()->IsTrackingMetadata());
  2483. // There were three entities with the same client-tag-hash which indicates
  2484. // that two of them were metadata oprhans.
  2485. histogram_tester.ExpectBucketCount(
  2486. "Sync.ModelTypeOrphanMetadata.ModelReadyToSync",
  2487. /*bucket=*/ModelTypeHistogramValue(GetModelType()),
  2488. /*count=*/2);
  2489. }
  2490. } // namespace syncer