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