15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/glue/non_ui_data_type_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/data_type_controller_mock.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/glue/non_ui_data_type_controller_mock.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/shared_change_processor_mock.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_components_factory_mock.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_mock.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/fake_syncable_service.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/engine/model_safe_worker.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace browser_sync {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::WaitableEvent;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::AUTOFILL_PROFILE;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::_;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::AtLeast;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::DoAll;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::InvokeWithoutArgs;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Mock;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Return;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::SetArgumentPointee;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::StrictMock;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(WaitOnEvent, event) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->Wait();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(SignalEvent, event) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->Signal();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(SaveChangeProcessor, scoped_change_processor) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_change_processor->reset(arg2);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(GetWeakPtrToSyncableService, syncable_service) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Have to do this within an Action to ensure it's not evaluated on the wrong
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return syncable_service->AsWeakPtr();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class NonUIDataTypeControllerFake
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public NonUIDataTypeController {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NonUIDataTypeControllerFake(
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProfileSyncComponentsFactory* profile_sync_factory,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Profile* profile,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProfileSyncService* sync_service,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NonUIDataTypeControllerMock* mock)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : NonUIDataTypeController(profile_sync_factory,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         profile,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         sync_service),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_(false),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mock_(mock) {}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual syncer::ModelType type() const OVERRIDE {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AUTOFILL_PROFILE;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual syncer::ModelSafeGroup model_safe_group() const OVERRIDE {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return syncer::GROUP_DB;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prevent tasks from being posted on the backend thread until
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UnblockBackendTasks() is called.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BlockBackendTasks() {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_ = true;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post pending tasks on the backend thread and start allowing tasks
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be posted on the backend thread again.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UnblockBackendTasks() {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_ = false;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<PendingTask>::const_iterator it = pending_tasks_.begin();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != pending_tasks_.end(); ++it) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostTaskOnBackendThread(it->from_here, it->task);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_tasks_.clear();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool PostTaskOnBackendThread(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const tracked_objects::Location& from_here,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Closure& task) OVERRIDE {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (blocked_) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_tasks_.push_back(PendingTask(from_here, task));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return BrowserThread::PostTask(BrowserThread::DB, from_here, task);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We mock the following methods because their default implementations do
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // nothing, but we still want to make sure they're called appropriately.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool StartModels() OVERRIDE {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return mock_->StartModels();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StopModels() OVERRIDE {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_->StopModels();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RecordUnrecoverableError(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const tracked_objects::Location& from_here,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& message) OVERRIDE {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_->RecordUnrecoverableError(from_here, message);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RecordAssociationTime(base::TimeDelta time) OVERRIDE {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_->RecordAssociationTime(time);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RecordStartFailure(DataTypeController::StartResult result)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OVERRIDE {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_->RecordStartFailure(result);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~NonUIDataTypeControllerFake() {}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NonUIDataTypeControllerFake);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct PendingTask {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingTask(const tracked_objects::Location& from_here,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const base::Closure& task)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : from_here(from_here), task(task) {}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tracked_objects::Location from_here;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Closure task;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool blocked_;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PendingTask> pending_tasks_;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NonUIDataTypeControllerMock* mock_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncNonUIDataTypeControllerTest : public testing::Test {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncNonUIDataTypeControllerTest()
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ui_thread_(BrowserThread::UI, &message_loop_),
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        db_thread_(BrowserThread::DB), service_(&profile_) {}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(service_, GetUserShare()).WillRepeatedly(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Return((syncer::UserShare*)NULL));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_thread_.Start();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_sync_factory_.reset(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new StrictMock<ProfileSyncComponentsFactoryMock>());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    change_processor_ = new SharedChangeProcessorMock();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // All of these are refcounted, so don't need to be released.
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dtc_mock_ = new StrictMock<NonUIDataTypeControllerMock>();
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    non_ui_dtc_ =
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new NonUIDataTypeControllerFake(profile_sync_factory_.get(),
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        &profile_,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        &service_,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        dtc_mock_.get());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_thread_.Stop();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForDTC() {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitableEvent done(true, false);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       base::Bind(&SyncNonUIDataTypeControllerTest::SignalDone,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  &done));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done.TimedWait(TestTimeouts::action_timeout());
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!done.IsSignaled()) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE() << "Timed out waiting for DB thread to finish.";
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->RunUntilIdle();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetStartExpectations() {
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(true));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(model_load_callback_, Run(_, _));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(*profile_sync_factory_,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                CreateSharedChangeProcessor()).
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WillOnce(Return(change_processor_.get()));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetAssociateExpectations() {
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _))
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        .WillOnce(Return(true));
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), ActivateDataType(_));
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        .WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_,_))
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        .WillOnce(Return(syncer::SyncError()));
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), GetSyncCount()).WillOnce(Return(0));
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetActivateExpectations(DataTypeController::StartResult result) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(start_callback_, Run(result,_,_));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetStopExpectations() {
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), StopModels());
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), Disconnect()).WillOnce(Return(true));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(service_, DeactivateDataType(_));
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetStartFailExpectations(DataTypeController::StartResult result) {
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), StopModels()).Times(AtLeast(1));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (DataTypeController::IsUnrecoverableResult(result))
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, _));
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), RecordStartFailure(result));
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(start_callback_, Run(result, _, _));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Start() {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    non_ui_dtc_->LoadModels(
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ModelLoadCallbackMock::Run,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(&model_load_callback_)));
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    non_ui_dtc_->StartAssociating(
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&StartCallbackMock::Run,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(&start_callback_)));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void SignalDone(WaitableEvent* done) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done->Signal();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForUI message_loop_;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread db_thread_;
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TestingProfile profile_;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<ProfileSyncServiceMock> service_;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartCallbackMock start_callback_;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModelLoadCallbackMock model_load_callback_;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Must be destroyed after non_ui_dtc_.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::FakeSyncableService syncable_service_;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<NonUIDataTypeControllerFake> non_ui_dtc_;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<NonUIDataTypeControllerMock> dtc_mock_;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SharedChangeProcessorMock> change_processor_;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<syncer::SyncChangeProcessor> saved_change_processor_;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StartOk) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StartFirstRun) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _))
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(true));
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_,_))
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(syncer::SyncError()));
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start the DTC and have StartModels() return false.  Then, stop the
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DTC without finishing model startup.  It should stop cleanly.
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, AbortDuringStartModels) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(*profile_sync_factory_,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              CreateSharedChangeProcessor()).
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WillOnce(Return(change_processor_.get()));
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(false));
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), StopModels());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(model_load_callback_, Run(_, _));
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->LoadModels(
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ModelLoadCallbackMock::Run,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(&model_load_callback_)));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::MODEL_STARTING, non_ui_dtc_->state());
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start the DTC and have MergeDataAndStartSyncing() return an error.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The DTC should become disabled, and the DTC should still stop
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cleanly.
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StartAssociationFailed) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _))
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(true));
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_,_))
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(syncer::SyncError()));
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up association to fail with an association failed error.
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncable_service_.set_merge_data_and_start_syncing_error(
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncer::SyncError(FROM_HERE,
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        syncer::SyncError::DATATYPE_ERROR,
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        "Sync Error",
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        non_ui_dtc_->type()));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::DISABLED, non_ui_dtc_->state());
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       StartAssociationTriggersUnrecoverableError) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up association to fail with an unrecoverable error.
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _))
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillRepeatedly(Return(true));
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       StartAssociationCryptoNotReady) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up association to fail with a NEEDS_CRYPTO error.
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _))
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillRepeatedly(Return(false));
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Trigger a Stop() call when we check if the model associator has user created
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// nodes.
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, AbortDuringAssociation) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent wait_for_db_thread_pause(false, false);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent pause_db_thread(false, false);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartFailExpectations(DataTypeController::ABORTED);
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _))
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(true));
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(DoAll(SignalEvent(&wait_for_db_thread_pause),
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      WaitOnEvent(&pause_db_thread),
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      SetArgumentPointee<0>(true),
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      Return(true)));
38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_,_))
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      .WillOnce(
38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          Return(syncer::SyncError(FROM_HERE,
38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   syncer::SyncError::DATATYPE_ERROR,
38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   "Disconnected.",
38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   AUTOFILL_PROFILE)));
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Disconnect())
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(DoAll(SignalEvent(&pause_db_thread), Return(true)));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(service_, DeactivateDataType(_));
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_for_db_thread_pause.Wait();
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start the DTC while the backend tasks are blocked. Then stop the DTC before
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the backend tasks get a chance to run. The DTC should have no interaction
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with the profile sync factory or profile sync service once stopped.
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StartAfterSyncShutdown) {
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->BlockBackendTasks();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't expect StopSyncing to be called because local_service_ will never
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have been set.
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Disconnect()).WillOnce(Return(true));
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), StopModels());
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(service_, DeactivateDataType(_));
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(),
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              RecordStartFailure(DataTypeController::ABORTED));
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED, _, _));
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&profile_sync_factory_);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&service_);
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Mock::VerifyAndClearExpectations(change_processor_.get());
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Mock::VerifyAndClearExpectations(dtc_mock_.get());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _))
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(base::WeakPtr<syncer::SyncableService>()));
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->UnblockBackendTasks();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, Stop) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStopExpectations();
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start the DTC then block its backend tasks.  While its backend
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tasks are blocked, stop and start it again, then unblock its
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// backend tasks.  The (delayed) running of the backend tasks from the
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stop after the restart shouldn't cause any problems.
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StopStart) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStopExpectations();
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->BlockBackendTasks();
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&profile_sync_factory_);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->UnblockBackendTasks();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest,
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       OnSingleDatatypeUnrecoverableError) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, "Test"));
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(service_, DisableBrokenDatatype(_, _, _)).WillOnce(
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      InvokeWithoutArgs(non_ui_dtc_.get(), &NonUIDataTypeController::Stop));
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStopExpectations();
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should cause non_ui_dtc_->Stop() to be called.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, base::Bind(
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &NonUIDataTypeControllerFake::
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          OnSingleDatatypeUnrecoverableError,
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      non_ui_dtc_.get(),
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string("Test")));
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace browser_sync
499