OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 | |
5 #include "components/sync_driver/glue/sync_backend_host_impl.h" | |
6 | |
7 #include <cstddef> | |
8 | |
9 #include "base/files/file_util.h" | |
10 #include "base/location.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/synchronization/waitable_event.h" | |
14 #include "base/test/test_timeouts.h" | |
15 #include "base/time/time.h" | |
16 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" | |
17 #include "chrome/browser/sync/profile_sync_test_util.h" | |
18 #include "chrome/test/base/testing_browser_process.h" | |
19 #include "chrome/test/base/testing_profile.h" | |
20 #include "chrome/test/base/testing_profile_manager.h" | |
21 #include "components/invalidation/impl/invalidator_storage.h" | |
22 #include "components/invalidation/impl/profile_invalidation_provider.h" | |
23 #include "components/invalidation/public/invalidator_state.h" | |
24 #include "components/invalidation/public/object_id_invalidation_map.h" | |
25 #include "components/sync_driver/device_info.h" | |
26 #include "components/sync_driver/fake_sync_client.h" | |
27 #include "components/sync_driver/sync_frontend.h" | |
28 #include "components/sync_driver/sync_prefs.h" | |
29 #include "components/syncable_prefs/pref_service_syncable.h" | |
30 #include "content/public/browser/notification_service.h" | |
31 #include "content/public/test/test_browser_thread_bundle.h" | |
32 #include "content/public/test/test_utils.h" | |
33 #include "google/cacheinvalidation/include/types.h" | |
34 #include "google_apis/gaia/gaia_constants.h" | |
35 #include "net/url_request/test_url_fetcher_factory.h" | |
36 #include "net/url_request/url_request_context_getter.h" | |
37 #include "sync/internal_api/public/base/model_type.h" | |
38 #include "sync/internal_api/public/engine/model_safe_worker.h" | |
39 #include "sync/internal_api/public/engine/passive_model_worker.h" | |
40 #include "sync/internal_api/public/http_bridge_network_resources.h" | |
41 #include "sync/internal_api/public/network_resources.h" | |
42 #include "sync/internal_api/public/sessions/commit_counters.h" | |
43 #include "sync/internal_api/public/sessions/status_counters.h" | |
44 #include "sync/internal_api/public/sessions/update_counters.h" | |
45 #include "sync/internal_api/public/sync_manager_factory.h" | |
46 #include "sync/internal_api/public/test/fake_sync_manager.h" | |
47 #include "sync/internal_api/public/util/experiments.h" | |
48 #include "sync/protocol/encryption.pb.h" | |
49 #include "sync/protocol/sync_protocol_error.h" | |
50 #include "sync/test/callback_counter.h" | |
51 #include "sync/util/test_unrecoverable_error_handler.h" | |
52 #include "testing/gmock/include/gmock/gmock.h" | |
53 #include "testing/gtest/include/gtest/gtest.h" | |
54 #include "url/gurl.h" | |
55 | |
56 using content::BrowserThread; | |
57 using syncer::FakeSyncManager; | |
58 using syncer::SyncManager; | |
59 using ::testing::InvokeWithoutArgs; | |
60 using ::testing::StrictMock; | |
61 using ::testing::_; | |
62 | |
63 namespace browser_sync { | |
64 | |
65 namespace { | |
66 | |
67 const char kTestProfileName[] = "test-profile"; | |
68 | |
69 static const base::FilePath::CharType kTestSyncDir[] = | |
70 FILE_PATH_LITERAL("sync-test"); | |
71 | |
72 ACTION_P(Signal, event) { | |
73 event->Signal(); | |
74 } | |
75 | |
76 void QuitMessageLoop() { | |
77 base::MessageLoop::current()->QuitWhenIdle(); | |
78 } | |
79 | |
80 class MockSyncFrontend : public sync_driver::SyncFrontend { | |
81 public: | |
82 virtual ~MockSyncFrontend() {} | |
83 | |
84 MOCK_METHOD4( | |
85 OnBackendInitialized, | |
86 void(const syncer::WeakHandle<syncer::JsBackend>&, | |
87 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&, | |
88 const std::string&, | |
89 bool)); | |
90 MOCK_METHOD0(OnSyncCycleCompleted, void()); | |
91 MOCK_METHOD1(OnConnectionStatusChange, | |
92 void(syncer::ConnectionStatus status)); | |
93 MOCK_METHOD0(OnClearServerDataSucceeded, void()); | |
94 MOCK_METHOD0(OnClearServerDataFailed, void()); | |
95 MOCK_METHOD2(OnPassphraseRequired, | |
96 void(syncer::PassphraseRequiredReason, | |
97 const sync_pb::EncryptedData&)); | |
98 MOCK_METHOD0(OnPassphraseAccepted, void()); | |
99 MOCK_METHOD2(OnEncryptedTypesChanged, | |
100 void(syncer::ModelTypeSet, bool)); | |
101 MOCK_METHOD0(OnEncryptionComplete, void()); | |
102 MOCK_METHOD1(OnMigrationNeededForTypes, void(syncer::ModelTypeSet)); | |
103 MOCK_METHOD1(OnProtocolEvent, void(const syncer::ProtocolEvent&)); | |
104 MOCK_METHOD2(OnDirectoryTypeCommitCounterUpdated, | |
105 void(syncer::ModelType, const syncer::CommitCounters&)); | |
106 MOCK_METHOD2(OnDirectoryTypeUpdateCounterUpdated, | |
107 void(syncer::ModelType, const syncer::UpdateCounters&)); | |
108 MOCK_METHOD2(OnDirectoryTypeStatusCounterUpdated, | |
109 void(syncer::ModelType, const syncer::StatusCounters&)); | |
110 MOCK_METHOD1(OnExperimentsChanged, | |
111 void(const syncer::Experiments&)); | |
112 MOCK_METHOD1(OnActionableError, | |
113 void(const syncer::SyncProtocolError& sync_error)); | |
114 MOCK_METHOD0(OnSyncConfigureRetry, void()); | |
115 MOCK_METHOD1( | |
116 OnLocalSetPassphraseEncryption, | |
117 void(const syncer::SyncEncryptionHandler::NigoriState& nigori_state)); | |
118 }; | |
119 | |
120 class FakeSyncManagerFactory : public syncer::SyncManagerFactory { | |
121 public: | |
122 explicit FakeSyncManagerFactory(FakeSyncManager** fake_manager) | |
123 : SyncManagerFactory(NORMAL), | |
124 fake_manager_(fake_manager) { | |
125 *fake_manager_ = NULL; | |
126 } | |
127 ~FakeSyncManagerFactory() override {} | |
128 | |
129 // SyncManagerFactory implementation. Called on the sync thread. | |
130 scoped_ptr<SyncManager> CreateSyncManager( | |
131 const std::string& /* name */) override { | |
132 *fake_manager_ = new FakeSyncManager(initial_sync_ended_types_, | |
133 progress_marker_types_, | |
134 configure_fail_types_); | |
135 return scoped_ptr<SyncManager>(*fake_manager_); | |
136 } | |
137 | |
138 void set_initial_sync_ended_types(syncer::ModelTypeSet types) { | |
139 initial_sync_ended_types_ = types; | |
140 } | |
141 | |
142 void set_progress_marker_types(syncer::ModelTypeSet types) { | |
143 progress_marker_types_ = types; | |
144 } | |
145 | |
146 void set_configure_fail_types(syncer::ModelTypeSet types) { | |
147 configure_fail_types_ = types; | |
148 } | |
149 | |
150 private: | |
151 syncer::ModelTypeSet initial_sync_ended_types_; | |
152 syncer::ModelTypeSet progress_marker_types_; | |
153 syncer::ModelTypeSet configure_fail_types_; | |
154 FakeSyncManager** fake_manager_; | |
155 }; | |
156 | |
157 class BackendSyncClient : public sync_driver::FakeSyncClient { | |
158 public: | |
159 scoped_refptr<syncer::ModelSafeWorker> CreateModelWorkerForGroup( | |
160 syncer::ModelSafeGroup group, | |
161 syncer::WorkerLoopDestructionObserver* observer) override { | |
162 switch (group) { | |
163 case syncer::GROUP_PASSIVE: | |
164 return new syncer::PassiveModelWorker(observer); | |
165 default: | |
166 return nullptr; | |
167 } | |
168 } | |
169 }; | |
170 | |
171 class SyncBackendHostTest : public testing::Test { | |
172 protected: | |
173 SyncBackendHostTest() | |
174 : thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD), | |
175 profile_manager_(TestingBrowserProcess::GetGlobal()), | |
176 fake_manager_(NULL) {} | |
177 | |
178 ~SyncBackendHostTest() override {} | |
179 | |
180 void SetUp() override { | |
181 ASSERT_TRUE(profile_manager_.SetUp()); | |
182 profile_ = profile_manager_.CreateTestingProfile(kTestProfileName); | |
183 sync_prefs_.reset(new sync_driver::SyncPrefs(profile_->GetPrefs())); | |
184 backend_.reset(new SyncBackendHostImpl( | |
185 profile_->GetDebugName(), &sync_client_, | |
186 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), | |
187 invalidation::ProfileInvalidationProviderFactory::GetForProfile( | |
188 profile_) | |
189 ->GetInvalidationService(), | |
190 sync_prefs_->AsWeakPtr(), | |
191 profile_->GetPath().Append(base::FilePath(kTestSyncDir)))); | |
192 credentials_.email = "user@example.com"; | |
193 credentials_.sync_token = "sync_token"; | |
194 credentials_.scope_set.insert(GaiaConstants::kChromeSyncOAuth2Scope); | |
195 | |
196 fake_manager_factory_.reset(new FakeSyncManagerFactory(&fake_manager_)); | |
197 | |
198 // These types are always implicitly enabled. | |
199 enabled_types_.PutAll(syncer::ControlTypes()); | |
200 | |
201 // NOTE: We can't include Passwords or Typed URLs due to the Sync Backend | |
202 // Registrar removing them if it can't find their model workers. | |
203 enabled_types_.Put(syncer::BOOKMARKS); | |
204 enabled_types_.Put(syncer::PREFERENCES); | |
205 enabled_types_.Put(syncer::SESSIONS); | |
206 enabled_types_.Put(syncer::SEARCH_ENGINES); | |
207 enabled_types_.Put(syncer::AUTOFILL); | |
208 | |
209 network_resources_.reset(new syncer::HttpBridgeNetworkResources()); | |
210 } | |
211 | |
212 void TearDown() override { | |
213 if (backend_) { | |
214 backend_->StopSyncingForShutdown(); | |
215 backend_->Shutdown(syncer::STOP_SYNC); | |
216 } | |
217 backend_.reset(); | |
218 sync_prefs_.reset(); | |
219 profile_ = NULL; | |
220 profile_manager_.DeleteTestingProfile(kTestProfileName); | |
221 // Pump messages posted by the sync thread (which may end up | |
222 // posting on the IO thread). | |
223 base::RunLoop().RunUntilIdle(); | |
224 content::RunAllPendingInMessageLoop(BrowserThread::IO); | |
225 // Pump any messages posted by the IO thread. | |
226 base::RunLoop().RunUntilIdle(); | |
227 } | |
228 | |
229 // Synchronously initializes the backend. | |
230 void InitializeBackend(bool expect_success) { | |
231 EXPECT_CALL(mock_frontend_, OnBackendInitialized(_, _, _, expect_success)). | |
232 WillOnce(InvokeWithoutArgs(QuitMessageLoop)); | |
233 SyncBackendHost::HttpPostProviderFactoryGetter | |
234 http_post_provider_factory_getter = | |
235 base::Bind(&syncer::NetworkResources::GetHttpPostProviderFactory, | |
236 base::Unretained(network_resources_.get()), | |
237 make_scoped_refptr(profile_->GetRequestContext()), | |
238 base::Bind(&EmptyNetworkTimeUpdate)); | |
239 backend_->Initialize( | |
240 &mock_frontend_, scoped_ptr<base::Thread>(), | |
241 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), | |
242 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), | |
243 syncer::WeakHandle<syncer::JsEventHandler>(), GURL(std::string()), | |
244 std::string(), credentials_, true, fake_manager_factory_.Pass(), | |
245 MakeWeakHandle(test_unrecoverable_error_handler_.GetWeakPtr()), | |
246 base::Closure(), http_post_provider_factory_getter, | |
247 saved_nigori_state_.Pass()); | |
248 base::RunLoop run_loop; | |
249 BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, | |
250 run_loop.QuitClosure(), | |
251 TestTimeouts::action_timeout()); | |
252 run_loop.Run(); | |
253 // |fake_manager_factory_|'s fake_manager() is set on the sync | |
254 // thread, but we can rely on the message loop barriers to | |
255 // guarantee that we see the updated value. | |
256 DCHECK(fake_manager_); | |
257 } | |
258 | |
259 // Synchronously configures the backend's datatypes. | |
260 syncer::ModelTypeSet ConfigureDataTypes( | |
261 syncer::ModelTypeSet types_to_add, | |
262 syncer::ModelTypeSet types_to_remove, | |
263 syncer::ModelTypeSet types_to_unapply) { | |
264 sync_driver::BackendDataTypeConfigurer::DataTypeConfigStateMap | |
265 config_state_map; | |
266 sync_driver::BackendDataTypeConfigurer::SetDataTypesState( | |
267 sync_driver::BackendDataTypeConfigurer::CONFIGURE_ACTIVE, | |
268 types_to_add, | |
269 &config_state_map); | |
270 sync_driver::BackendDataTypeConfigurer::SetDataTypesState( | |
271 sync_driver::BackendDataTypeConfigurer::DISABLED, | |
272 types_to_remove, &config_state_map); | |
273 sync_driver::BackendDataTypeConfigurer::SetDataTypesState( | |
274 sync_driver::BackendDataTypeConfigurer::UNREADY, | |
275 types_to_unapply, &config_state_map); | |
276 | |
277 types_to_add.PutAll(syncer::ControlTypes()); | |
278 syncer::ModelTypeSet ready_types = backend_->ConfigureDataTypes( | |
279 syncer::CONFIGURE_REASON_RECONFIGURATION, config_state_map, | |
280 base::Bind(&SyncBackendHostTest::DownloadReady, base::Unretained(this)), | |
281 base::Bind(&SyncBackendHostTest::OnDownloadRetry, | |
282 base::Unretained(this))); | |
283 base::RunLoop run_loop; | |
284 BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, | |
285 run_loop.QuitClosure(), | |
286 TestTimeouts::action_timeout()); | |
287 run_loop.Run(); | |
288 return ready_types; | |
289 } | |
290 | |
291 protected: | |
292 void DownloadReady(syncer::ModelTypeSet succeeded_types, | |
293 syncer::ModelTypeSet failed_types) { | |
294 base::MessageLoop::current()->QuitWhenIdle(); | |
295 } | |
296 | |
297 void OnDownloadRetry() { | |
298 NOTIMPLEMENTED(); | |
299 } | |
300 | |
301 content::TestBrowserThreadBundle thread_bundle_; | |
302 StrictMock<MockSyncFrontend> mock_frontend_; | |
303 syncer::SyncCredentials credentials_; | |
304 TestingProfileManager profile_manager_; | |
305 TestingProfile* profile_; | |
306 BackendSyncClient sync_client_; | |
307 syncer::TestUnrecoverableErrorHandler test_unrecoverable_error_handler_; | |
308 scoped_ptr<sync_driver::SyncPrefs> sync_prefs_; | |
309 scoped_ptr<SyncBackendHostImpl> backend_; | |
310 scoped_ptr<FakeSyncManagerFactory> fake_manager_factory_; | |
311 FakeSyncManager* fake_manager_; | |
312 syncer::ModelTypeSet enabled_types_; | |
313 scoped_ptr<syncer::NetworkResources> network_resources_; | |
314 scoped_ptr<syncer::SyncEncryptionHandler::NigoriState> saved_nigori_state_; | |
315 }; | |
316 | |
317 // Test basic initialization with no initial types (first time initialization). | |
318 // Only the nigori should be configured. | |
319 TEST_F(SyncBackendHostTest, InitShutdown) { | |
320 InitializeBackend(true); | |
321 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
322 syncer::ControlTypes())); | |
323 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals( | |
324 syncer::ControlTypes())); | |
325 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
326 syncer::ControlTypes()).Empty()); | |
327 } | |
328 | |
329 // Test first time sync scenario. All types should be properly configured. | |
330 TEST_F(SyncBackendHostTest, FirstTimeSync) { | |
331 InitializeBackend(true); | |
332 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
333 syncer::ControlTypes())); | |
334 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals( | |
335 syncer::ControlTypes())); | |
336 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
337 syncer::ControlTypes()).Empty()); | |
338 | |
339 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
340 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
341 syncer::ModelTypeSet()); | |
342 // Nigori is always downloaded so won't be ready. | |
343 EXPECT_TRUE(ready_types.Equals(syncer::Difference( | |
344 syncer::ControlTypes(), | |
345 syncer::ModelTypeSet(syncer::NIGORI)))); | |
346 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().HasAll( | |
347 Difference(enabled_types_, syncer::ControlTypes()))); | |
348 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
349 EXPECT_TRUE(fake_manager_->GetAndResetEnabledTypes().Equals(enabled_types_)); | |
350 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
351 enabled_types_).Empty()); | |
352 } | |
353 | |
354 // Test the restart after setting up sync scenario. No enabled types should be | |
355 // downloaded or cleaned. | |
356 TEST_F(SyncBackendHostTest, Restart) { | |
357 sync_prefs_->SetSyncSetupCompleted(); | |
358 syncer::ModelTypeSet all_but_nigori = enabled_types_; | |
359 fake_manager_factory_->set_progress_marker_types(enabled_types_); | |
360 fake_manager_factory_->set_initial_sync_ended_types(enabled_types_); | |
361 InitializeBackend(true); | |
362 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Empty()); | |
363 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
364 enabled_types_).Empty()); | |
365 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
366 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
367 enabled_types_).Empty()); | |
368 | |
369 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
370 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
371 syncer::ModelTypeSet()); | |
372 EXPECT_TRUE(ready_types.Equals(enabled_types_)); | |
373 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Empty()); | |
374 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
375 enabled_types_).Empty()); | |
376 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
377 EXPECT_TRUE(fake_manager_->GetAndResetEnabledTypes().Equals(enabled_types_)); | |
378 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
379 enabled_types_).Empty()); | |
380 } | |
381 | |
382 // Test a sync restart scenario where some types had never finished configuring. | |
383 // The partial types should be purged, then reconfigured properly. | |
384 TEST_F(SyncBackendHostTest, PartialTypes) { | |
385 sync_prefs_->SetSyncSetupCompleted(); | |
386 // Set sync manager behavior before passing it down. All types have progress | |
387 // markers, but nigori and bookmarks are missing initial sync ended. | |
388 syncer::ModelTypeSet partial_types(syncer::NIGORI, syncer::BOOKMARKS); | |
389 syncer::ModelTypeSet full_types = | |
390 Difference(enabled_types_, partial_types); | |
391 fake_manager_factory_->set_progress_marker_types(enabled_types_); | |
392 fake_manager_factory_->set_initial_sync_ended_types(full_types); | |
393 | |
394 // Bringing up the backend should purge all partial types, then proceed to | |
395 // download the Nigori. | |
396 InitializeBackend(true); | |
397 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
398 syncer::ModelTypeSet(syncer::NIGORI))); | |
399 EXPECT_TRUE(fake_manager_->GetAndResetCleanedTypes().HasAll(partial_types)); | |
400 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals( | |
401 Union(full_types, syncer::ModelTypeSet(syncer::NIGORI)))); | |
402 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
403 enabled_types_).Equals( | |
404 Difference(partial_types, syncer::ModelTypeSet(syncer::NIGORI)))); | |
405 | |
406 // Now do the actual configuration, which should download and apply bookmarks. | |
407 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
408 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
409 syncer::ModelTypeSet()); | |
410 EXPECT_TRUE(ready_types.Equals(full_types)); | |
411 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
412 enabled_types_).Empty()); | |
413 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
414 partial_types)); | |
415 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
416 EXPECT_TRUE(fake_manager_->GetAndResetEnabledTypes().Equals(enabled_types_)); | |
417 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
418 enabled_types_).Empty()); | |
419 } | |
420 | |
421 // Test the behavior when we lose the sync db. Although we already have types | |
422 // enabled, we should re-download all of them because we lost their data. | |
423 TEST_F(SyncBackendHostTest, LostDB) { | |
424 sync_prefs_->SetSyncSetupCompleted(); | |
425 // Initialization should fetch the Nigori node. Everything else should be | |
426 // left untouched. | |
427 InitializeBackend(true); | |
428 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
429 syncer::ModelTypeSet(syncer::ControlTypes()))); | |
430 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals( | |
431 syncer::ModelTypeSet(syncer::ControlTypes()))); | |
432 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
433 enabled_types_).Equals( | |
434 Difference(enabled_types_, syncer::ControlTypes()))); | |
435 | |
436 // The database was empty, so any cleaning is entirely optional. We want to | |
437 // reset this value before running the next part of the test, though. | |
438 fake_manager_->GetAndResetCleanedTypes(); | |
439 | |
440 // The actual configuration should redownload and apply all the enabled types. | |
441 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
442 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
443 syncer::ModelTypeSet()); | |
444 // Nigori is always downloaded so won't be ready. | |
445 EXPECT_TRUE(ready_types.Equals(syncer::Difference( | |
446 syncer::ControlTypes(), | |
447 syncer::ModelTypeSet(syncer::NIGORI)))); | |
448 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().HasAll( | |
449 Difference(enabled_types_, syncer::ControlTypes()))); | |
450 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
451 enabled_types_).Empty()); | |
452 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
453 EXPECT_TRUE(fake_manager_->GetAndResetEnabledTypes().Equals(enabled_types_)); | |
454 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
455 enabled_types_).Empty()); | |
456 } | |
457 | |
458 TEST_F(SyncBackendHostTest, DisableTypes) { | |
459 // Simulate first time sync. | |
460 InitializeBackend(true); | |
461 fake_manager_->GetAndResetCleanedTypes(); | |
462 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
463 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
464 syncer::ModelTypeSet()); | |
465 // Nigori is always downloaded so won't be ready. | |
466 EXPECT_TRUE(ready_types.Equals(syncer::Difference( | |
467 syncer::ControlTypes(), | |
468 syncer::ModelTypeSet(syncer::NIGORI)))); | |
469 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
470 enabled_types_)); | |
471 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
472 enabled_types_).Empty()); | |
473 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
474 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
475 enabled_types_).Empty()); | |
476 | |
477 // Then disable two datatypes. | |
478 syncer::ModelTypeSet disabled_types(syncer::BOOKMARKS, | |
479 syncer::SEARCH_ENGINES); | |
480 syncer::ModelTypeSet old_types = enabled_types_; | |
481 enabled_types_.RemoveAll(disabled_types); | |
482 ready_types = ConfigureDataTypes( | |
483 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
484 syncer::ModelTypeSet()); | |
485 | |
486 // Only those datatypes disabled should be cleaned. Nothing should be | |
487 // downloaded. | |
488 EXPECT_TRUE(ready_types.Equals(enabled_types_)); | |
489 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Empty()); | |
490 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
491 old_types).Equals(disabled_types)); | |
492 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
493 EXPECT_TRUE(fake_manager_->GetAndResetEnabledTypes().Equals(enabled_types_)); | |
494 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
495 enabled_types_).Empty()); | |
496 } | |
497 | |
498 TEST_F(SyncBackendHostTest, AddTypes) { | |
499 // Simulate first time sync. | |
500 InitializeBackend(true); | |
501 fake_manager_->GetAndResetCleanedTypes(); | |
502 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
503 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
504 syncer::ModelTypeSet()); | |
505 // Nigori is always downloaded so won't be ready. | |
506 EXPECT_TRUE(ready_types.Equals(syncer::Difference( | |
507 syncer::ControlTypes(), | |
508 syncer::ModelTypeSet(syncer::NIGORI)))); | |
509 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
510 enabled_types_)); | |
511 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
512 enabled_types_).Empty()); | |
513 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
514 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
515 enabled_types_).Empty()); | |
516 | |
517 // Then add two datatypes. | |
518 syncer::ModelTypeSet new_types(syncer::EXTENSIONS, | |
519 syncer::APPS); | |
520 enabled_types_.PutAll(new_types); | |
521 ready_types = ConfigureDataTypes( | |
522 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
523 syncer::ModelTypeSet()); | |
524 | |
525 // Only those datatypes added should be downloaded (plus nigori). Nothing | |
526 // should be cleaned aside from the disabled types. | |
527 new_types.Put(syncer::NIGORI); | |
528 EXPECT_TRUE( | |
529 ready_types.Equals(syncer::Difference(enabled_types_, new_types))); | |
530 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals(new_types)); | |
531 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
532 enabled_types_).Empty()); | |
533 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
534 EXPECT_TRUE(fake_manager_->GetAndResetEnabledTypes().Equals(enabled_types_)); | |
535 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
536 enabled_types_).Empty()); | |
537 } | |
538 | |
539 // And and disable in the same configuration. | |
540 TEST_F(SyncBackendHostTest, AddDisableTypes) { | |
541 // Simulate first time sync. | |
542 InitializeBackend(true); | |
543 fake_manager_->GetAndResetCleanedTypes(); | |
544 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
545 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
546 syncer::ModelTypeSet()); | |
547 // Nigori is always downloaded so won't be ready. | |
548 EXPECT_TRUE(ready_types.Equals(syncer::Difference( | |
549 syncer::ControlTypes(), | |
550 syncer::ModelTypeSet(syncer::NIGORI)))); | |
551 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
552 enabled_types_)); | |
553 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
554 enabled_types_).Empty()); | |
555 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
556 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
557 enabled_types_).Empty()); | |
558 | |
559 // Then add two datatypes. | |
560 syncer::ModelTypeSet old_types = enabled_types_; | |
561 syncer::ModelTypeSet disabled_types(syncer::BOOKMARKS, | |
562 syncer::SEARCH_ENGINES); | |
563 syncer::ModelTypeSet new_types(syncer::EXTENSIONS, | |
564 syncer::APPS); | |
565 enabled_types_.PutAll(new_types); | |
566 enabled_types_.RemoveAll(disabled_types); | |
567 ready_types = ConfigureDataTypes( | |
568 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
569 syncer::ModelTypeSet()); | |
570 | |
571 // Only those datatypes added should be downloaded (plus nigori). Nothing | |
572 // should be cleaned aside from the disabled types. | |
573 new_types.Put(syncer::NIGORI); | |
574 EXPECT_TRUE( | |
575 ready_types.Equals(syncer::Difference(enabled_types_, new_types))); | |
576 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals(new_types)); | |
577 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
578 old_types).Equals(disabled_types)); | |
579 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
580 EXPECT_TRUE(fake_manager_->GetAndResetEnabledTypes().Equals(enabled_types_)); | |
581 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
582 old_types).Equals(disabled_types)); | |
583 } | |
584 | |
585 // Test restarting the browser to newly supported datatypes. The new datatypes | |
586 // should be downloaded on the configuration after backend initialization. | |
587 TEST_F(SyncBackendHostTest, NewlySupportedTypes) { | |
588 sync_prefs_->SetSyncSetupCompleted(); | |
589 // Set sync manager behavior before passing it down. All types have progress | |
590 // markers and initial sync ended except the new types. | |
591 syncer::ModelTypeSet old_types = enabled_types_; | |
592 fake_manager_factory_->set_progress_marker_types(old_types); | |
593 fake_manager_factory_->set_initial_sync_ended_types(old_types); | |
594 syncer::ModelTypeSet new_types(syncer::APP_SETTINGS, | |
595 syncer::EXTENSION_SETTINGS); | |
596 enabled_types_.PutAll(new_types); | |
597 | |
598 // Does nothing. | |
599 InitializeBackend(true); | |
600 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Empty()); | |
601 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
602 old_types).Empty()); | |
603 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(old_types)); | |
604 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
605 enabled_types_).Equals(new_types)); | |
606 | |
607 // Downloads and applies the new types (plus nigori). | |
608 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
609 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
610 syncer::ModelTypeSet()); | |
611 | |
612 new_types.Put(syncer::NIGORI); | |
613 EXPECT_TRUE(ready_types.Equals( | |
614 syncer::Difference(old_types, syncer::ModelTypeSet(syncer::NIGORI)))); | |
615 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals(new_types)); | |
616 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
617 enabled_types_).Empty()); | |
618 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
619 EXPECT_TRUE(fake_manager_->GetAndResetEnabledTypes().Equals(enabled_types_)); | |
620 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
621 enabled_types_).Empty()); | |
622 } | |
623 | |
624 // Test the newly supported types scenario, but with the presence of partial | |
625 // types as well. Both partial and newly supported types should be downloaded | |
626 // the configuration. | |
627 TEST_F(SyncBackendHostTest, NewlySupportedTypesWithPartialTypes) { | |
628 sync_prefs_->SetSyncSetupCompleted(); | |
629 // Set sync manager behavior before passing it down. All types have progress | |
630 // markers and initial sync ended except the new types. | |
631 syncer::ModelTypeSet old_types = enabled_types_; | |
632 syncer::ModelTypeSet partial_types(syncer::NIGORI, syncer::BOOKMARKS); | |
633 syncer::ModelTypeSet full_types = | |
634 Difference(enabled_types_, partial_types); | |
635 fake_manager_factory_->set_progress_marker_types(old_types); | |
636 fake_manager_factory_->set_initial_sync_ended_types(full_types); | |
637 syncer::ModelTypeSet new_types(syncer::APP_SETTINGS, | |
638 syncer::EXTENSION_SETTINGS); | |
639 enabled_types_.PutAll(new_types); | |
640 | |
641 // Purge the partial types. The nigori will be among the purged types, but | |
642 // the syncer will re-download it by the time the initialization is complete. | |
643 InitializeBackend(true); | |
644 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
645 syncer::ModelTypeSet(syncer::NIGORI))); | |
646 EXPECT_TRUE(fake_manager_->GetAndResetCleanedTypes().HasAll(partial_types)); | |
647 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals( | |
648 syncer::Union(full_types, syncer::ModelTypeSet(syncer::NIGORI)))); | |
649 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
650 enabled_types_).Equals(Union(new_types, Difference( | |
651 partial_types, syncer::ModelTypeSet(syncer::NIGORI))))); | |
652 | |
653 // Downloads and applies the new types and partial types (which includes | |
654 // nigori anyways). | |
655 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
656 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
657 syncer::ModelTypeSet()); | |
658 EXPECT_TRUE(ready_types.Equals(full_types)); | |
659 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals( | |
660 Union(new_types, partial_types))); | |
661 EXPECT_TRUE(Intersection(fake_manager_->GetAndResetCleanedTypes(), | |
662 enabled_types_).Empty()); | |
663 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
664 EXPECT_TRUE(fake_manager_->GetAndResetEnabledTypes().Equals(enabled_types_)); | |
665 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
666 enabled_types_).Empty()); | |
667 } | |
668 | |
669 // Verify that downloading control types only downloads those types that do | |
670 // not have initial sync ended set. | |
671 TEST_F(SyncBackendHostTest, DownloadControlTypes) { | |
672 sync_prefs_->SetSyncSetupCompleted(); | |
673 // Set sync manager behavior before passing it down. Experiments and device | |
674 // info are new types without progress markers or initial sync ended, while | |
675 // all other types have been fully downloaded and applied. | |
676 syncer::ModelTypeSet new_types(syncer::EXPERIMENTS, syncer::NIGORI); | |
677 syncer::ModelTypeSet old_types = | |
678 Difference(enabled_types_, new_types); | |
679 fake_manager_factory_->set_progress_marker_types(old_types); | |
680 fake_manager_factory_->set_initial_sync_ended_types(old_types); | |
681 | |
682 // Bringing up the backend should download the new types without downloading | |
683 // any old types. | |
684 InitializeBackend(true); | |
685 EXPECT_TRUE(fake_manager_->GetAndResetDownloadedTypes().Equals(new_types)); | |
686 EXPECT_TRUE(fake_manager_->GetAndResetCleanedTypes().Equals( | |
687 Difference(syncer::ModelTypeSet::All(), | |
688 enabled_types_))); | |
689 EXPECT_TRUE(fake_manager_->InitialSyncEndedTypes().Equals(enabled_types_)); | |
690 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
691 enabled_types_).Empty()); | |
692 } | |
693 | |
694 // Fail to download control types. It's believed that there is a server bug | |
695 // which can allow this to happen (crbug.com/164288). The sync backend host | |
696 // should detect this condition and fail to initialize the backend. | |
697 // | |
698 // The failure is "silent" in the sense that the GetUpdates request appears to | |
699 // be successful, but it returned no results. This means that the usual | |
700 // download retry logic will not be invoked. | |
701 TEST_F(SyncBackendHostTest, SilentlyFailToDownloadControlTypes) { | |
702 fake_manager_factory_->set_configure_fail_types(syncer::ModelTypeSet::All()); | |
703 InitializeBackend(false); | |
704 } | |
705 | |
706 // Test that local refresh requests are delivered to sync. | |
707 TEST_F(SyncBackendHostTest, ForwardLocalRefreshRequest) { | |
708 InitializeBackend(true); | |
709 | |
710 syncer::ModelTypeSet set1 = syncer::ModelTypeSet::All(); | |
711 backend_->TriggerRefresh(set1); | |
712 fake_manager_->WaitForSyncThread(); | |
713 EXPECT_TRUE(set1.Equals(fake_manager_->GetLastRefreshRequestTypes())); | |
714 | |
715 syncer::ModelTypeSet set2 = syncer::ModelTypeSet(syncer::SESSIONS); | |
716 backend_->TriggerRefresh(set2); | |
717 fake_manager_->WaitForSyncThread(); | |
718 EXPECT_TRUE(set2.Equals(fake_manager_->GetLastRefreshRequestTypes())); | |
719 } | |
720 | |
721 // Test that configuration on signin sends the proper GU source. | |
722 TEST_F(SyncBackendHostTest, DownloadControlTypesNewClient) { | |
723 InitializeBackend(true); | |
724 EXPECT_EQ(syncer::CONFIGURE_REASON_NEW_CLIENT, | |
725 fake_manager_->GetAndResetConfigureReason()); | |
726 } | |
727 | |
728 // Test that configuration on restart sends the proper GU source. | |
729 TEST_F(SyncBackendHostTest, DownloadControlTypesRestart) { | |
730 sync_prefs_->SetSyncSetupCompleted(); | |
731 fake_manager_factory_->set_progress_marker_types(enabled_types_); | |
732 fake_manager_factory_->set_initial_sync_ended_types(enabled_types_); | |
733 InitializeBackend(true); | |
734 EXPECT_EQ(syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE, | |
735 fake_manager_->GetAndResetConfigureReason()); | |
736 } | |
737 | |
738 // It is SyncBackendHostCore responsibility to cleanup Sync Data folder if sync | |
739 // setup hasn't been completed. This test ensures that cleanup happens. | |
740 TEST_F(SyncBackendHostTest, TestStartupWithOldSyncData) { | |
741 const char* nonsense = "slon"; | |
742 base::FilePath temp_directory = | |
743 profile_->GetPath().Append(base::FilePath(kTestSyncDir)); | |
744 base::FilePath sync_file = temp_directory.AppendASCII("SyncData.sqlite3"); | |
745 ASSERT_TRUE(base::CreateDirectory(temp_directory)); | |
746 ASSERT_NE(-1, base::WriteFile(sync_file, nonsense, strlen(nonsense))); | |
747 | |
748 InitializeBackend(true); | |
749 | |
750 EXPECT_FALSE(base::PathExists(sync_file)); | |
751 } | |
752 | |
753 // If bookmarks encounter an error that results in disabling without purging | |
754 // (such as when the type is unready), and then is explicitly disabled, the | |
755 // SyncBackendHost needs to tell the manager to purge the type, even though | |
756 // it's already disabled (crbug.com/386778). | |
757 TEST_F(SyncBackendHostTest, DisableThenPurgeType) { | |
758 syncer::ModelTypeSet error_types(syncer::BOOKMARKS); | |
759 | |
760 InitializeBackend(true); | |
761 | |
762 // First enable the types. | |
763 syncer::ModelTypeSet ready_types = ConfigureDataTypes( | |
764 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
765 syncer::ModelTypeSet()); | |
766 | |
767 // Nigori is always downloaded so won't be ready. | |
768 EXPECT_TRUE(ready_types.Equals(syncer::Difference( | |
769 syncer::ControlTypes(), | |
770 syncer::ModelTypeSet(syncer::NIGORI)))); | |
771 | |
772 // Then mark the error types as unready (disables without purging). | |
773 ready_types = ConfigureDataTypes( | |
774 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
775 error_types); | |
776 EXPECT_TRUE( | |
777 ready_types.Equals(syncer::Difference(enabled_types_, error_types))); | |
778 EXPECT_TRUE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
779 error_types).Empty()); | |
780 | |
781 // Lastly explicitly disable the error types, which should result in a purge. | |
782 enabled_types_.RemoveAll(error_types); | |
783 ready_types = ConfigureDataTypes( | |
784 enabled_types_, Difference(syncer::ModelTypeSet::All(), enabled_types_), | |
785 syncer::ModelTypeSet()); | |
786 EXPECT_TRUE( | |
787 ready_types.Equals(syncer::Difference(enabled_types_, error_types))); | |
788 EXPECT_FALSE(fake_manager_->GetTypesWithEmptyProgressMarkerToken( | |
789 error_types).Empty()); | |
790 } | |
791 | |
792 // Test that a call to ClearServerData is forwarded to the underlying | |
793 // SyncManager. | |
794 TEST_F(SyncBackendHostTest, ClearServerDataCallsAreForwarded) { | |
795 InitializeBackend(true); | |
796 syncer::CallbackCounter callback_counter; | |
797 backend_->ClearServerData(base::Bind(&syncer::CallbackCounter::Callback, | |
798 base::Unretained(&callback_counter))); | |
799 fake_manager_->WaitForSyncThread(); | |
800 EXPECT_EQ(1, callback_counter.times_called()); | |
801 } | |
802 | |
803 // Ensure that redundant invalidations are ignored and that the most recent | |
804 // set of invalidation version is persisted across restarts. | |
805 TEST_F(SyncBackendHostTest, IgnoreOldInvalidations) { | |
806 // Set up some old persisted invalidations. | |
807 std::map<syncer::ModelType, int64> invalidation_versions; | |
808 invalidation_versions[syncer::BOOKMARKS] = 20; | |
809 sync_prefs_->UpdateInvalidationVersions(invalidation_versions); | |
810 InitializeBackend(true); | |
811 EXPECT_EQ(0, fake_manager_->GetInvalidationCount()); | |
812 | |
813 // Receiving an invalidation with an old version should do nothing. | |
814 syncer::ObjectIdInvalidationMap invalidation_map; | |
815 std::string notification_type; | |
816 syncer::RealModelTypeToNotificationType(syncer::BOOKMARKS, | |
817 ¬ification_type); | |
818 invalidation_map.Insert(syncer::Invalidation::Init( | |
819 invalidation::ObjectId(0, notification_type), 10, "payload")); | |
820 backend_->OnIncomingInvalidation(invalidation_map); | |
821 fake_manager_->WaitForSyncThread(); | |
822 EXPECT_EQ(0, fake_manager_->GetInvalidationCount()); | |
823 | |
824 // Invalidations with new versions should be acted upon. | |
825 invalidation_map.Insert(syncer::Invalidation::Init( | |
826 invalidation::ObjectId(0, notification_type), 30, "payload")); | |
827 backend_->OnIncomingInvalidation(invalidation_map); | |
828 fake_manager_->WaitForSyncThread(); | |
829 EXPECT_EQ(1, fake_manager_->GetInvalidationCount()); | |
830 | |
831 // Invalidation for new data types should be acted on. | |
832 syncer::RealModelTypeToNotificationType(syncer::SESSIONS, ¬ification_type); | |
833 invalidation_map.Insert(syncer::Invalidation::Init( | |
834 invalidation::ObjectId(0, notification_type), 10, "payload")); | |
835 backend_->OnIncomingInvalidation(invalidation_map); | |
836 fake_manager_->WaitForSyncThread(); | |
837 EXPECT_EQ(2, fake_manager_->GetInvalidationCount()); | |
838 | |
839 // But redelivering that same invalidation should be ignored. | |
840 backend_->OnIncomingInvalidation(invalidation_map); | |
841 fake_manager_->WaitForSyncThread(); | |
842 EXPECT_EQ(2, fake_manager_->GetInvalidationCount()); | |
843 | |
844 // If an invalidation with an unknown version is received, it should be | |
845 // acted on, but should not affect the persisted versions. | |
846 invalidation_map.Insert(syncer::Invalidation::InitUnknownVersion( | |
847 invalidation::ObjectId(0, notification_type))); | |
848 backend_->OnIncomingInvalidation(invalidation_map); | |
849 fake_manager_->WaitForSyncThread(); | |
850 EXPECT_EQ(3, fake_manager_->GetInvalidationCount()); | |
851 | |
852 // Verify that the invalidation versions were updated in the prefs. | |
853 invalidation_versions[syncer::BOOKMARKS] = 30; | |
854 invalidation_versions[syncer::SESSIONS] = 10; | |
855 std::map<syncer::ModelType, int64> persisted_invalidation_versions; | |
856 sync_prefs_->GetInvalidationVersions(&persisted_invalidation_versions); | |
857 EXPECT_EQ(invalidation_versions.size(), | |
858 persisted_invalidation_versions.size()); | |
859 for (auto iter : persisted_invalidation_versions) { | |
860 EXPECT_EQ(invalidation_versions[iter.first], iter.second); | |
861 } | |
862 } | |
863 | |
864 } // namespace | |
865 | |
866 } // namespace browser_sync | |
OLD | NEW |