1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 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)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/sync_driver/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"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/threading/thread.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/sync_driver/data_type_controller_mock.h"
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "components/sync_driver/generic_change_processor_factory.h"
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/sync_driver/non_ui_data_type_controller_mock.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/fake_syncable_service.h"
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "sync/api/sync_change.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/engine/model_safe_worker.h"
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace sync_driver {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::WaitableEvent;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::AUTOFILL_PROFILE;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::_;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::AtLeast;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::DoAll;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::InvokeWithoutArgs;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Mock;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Return;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::SetArgumentPointee;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::StrictMock;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(WaitOnEvent, event) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->Wait();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(SignalEvent, event) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->Signal();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(SaveChangeProcessor, scoped_change_processor) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_change_processor->reset(arg2);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(GetWeakPtrToSyncableService, syncable_service) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Have to do this within an Action to ensure it's not evaluated on the wrong
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return syncable_service->AsWeakPtr();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass SharedChangeProcessorMock : public SharedChangeProcessor {
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SharedChangeProcessorMock() {}
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  MOCK_METHOD6(Connect, base::WeakPtr<syncer::SyncableService>(
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SyncApiComponentFactory*,
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      GenericChangeProcessorFactory*,
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      syncer::UserShare*,
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DataTypeErrorHandler*,
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      syncer::ModelType,
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      const base::WeakPtr<syncer::SyncMergeResult>&));
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MOCK_METHOD0(Disconnect, bool());
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MOCK_METHOD2(ProcessSyncChanges,
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               syncer::SyncError(const tracked_objects::Location&,
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         const syncer::SyncChangeList&));
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MOCK_CONST_METHOD2(GetAllSyncDataReturnError,
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     syncer::SyncError(syncer::ModelType,
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       syncer::SyncDataList*));
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MOCK_METHOD0(GetSyncCount, int());
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MOCK_METHOD1(SyncModelHasUserCreatedNodes,
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu               bool(bool*));
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MOCK_METHOD0(CryptoReadyIfNecessary, bool());
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MOCK_CONST_METHOD1(GetDataTypeContext, bool(std::string*));
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu protected:
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual ~SharedChangeProcessorMock() {}
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MOCK_METHOD2(OnUnrecoverableError, void(const tracked_objects::Location&,
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                          const std::string&));
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DISALLOW_COPY_AND_ASSIGN(SharedChangeProcessorMock);
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class NonUIDataTypeControllerFake
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public NonUIDataTypeController {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NonUIDataTypeControllerFake(
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SyncApiComponentFactory* sync_factory,
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      NonUIDataTypeControllerMock* mock,
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SharedChangeProcessor* change_processor,
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      scoped_refptr<base::MessageLoopProxy> backend_loop)
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : NonUIDataTypeController(
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          base::MessageLoopProxy::current(),
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          base::Closure(),
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          sync_factory),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_(false),
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        mock_(mock),
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        change_processor_(change_processor),
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        backend_loop_(backend_loop) {}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual syncer::ModelType type() const OVERRIDE {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AUTOFILL_PROFILE;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual syncer::ModelSafeGroup model_safe_group() const OVERRIDE {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return syncer::GROUP_DB;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prevent tasks from being posted on the backend thread until
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UnblockBackendTasks() is called.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BlockBackendTasks() {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_ = true;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post pending tasks on the backend thread and start allowing tasks
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be posted on the backend thread again.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UnblockBackendTasks() {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_ = false;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<PendingTask>::const_iterator it = pending_tasks_.begin();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != pending_tasks_.end(); ++it) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostTaskOnBackendThread(it->from_here, it->task);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_tasks_.clear();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual SharedChangeProcessor* CreateSharedChangeProcessor() OVERRIDE {
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return change_processor_.get();
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool PostTaskOnBackendThread(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const tracked_objects::Location& from_here,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Closure& task) OVERRIDE {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (blocked_) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_tasks_.push_back(PendingTask(from_here, task));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return backend_loop_->PostTask(from_here, task);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We mock the following methods because their default implementations do
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // nothing, but we still want to make sure they're called appropriately.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool StartModels() OVERRIDE {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return mock_->StartModels();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StopModels() OVERRIDE {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_->StopModels();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RecordAssociationTime(base::TimeDelta time) OVERRIDE {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_->RecordAssociationTime(time);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void RecordStartFailure(DataTypeController::ConfigureResult result)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OVERRIDE {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_->RecordStartFailure(result);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~NonUIDataTypeControllerFake() {}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NonUIDataTypeControllerFake);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct PendingTask {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingTask(const tracked_objects::Location& from_here,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const base::Closure& task)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : from_here(from_here), task(task) {}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tracked_objects::Location from_here;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Closure task;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool blocked_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PendingTask> pending_tasks_;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NonUIDataTypeControllerMock* mock_;
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<SharedChangeProcessor> change_processor_;
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> backend_loop_;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncNonUIDataTypeControllerTest : public testing::Test {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncNonUIDataTypeControllerTest()
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      : backend_thread_("dbthread") {}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    backend_thread_.Start();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    change_processor_ = new SharedChangeProcessorMock();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // All of these are refcounted, so don't need to be released.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dtc_mock_ = new StrictMock<NonUIDataTypeControllerMock>();
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    non_ui_dtc_ =
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        new NonUIDataTypeControllerFake(NULL,
1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                        dtc_mock_.get(),
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        change_processor_.get(),
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        backend_thread_.message_loop_proxy());
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    backend_thread_.Stop();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForDTC() {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitableEvent done(true, false);
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    backend_thread_.message_loop_proxy()->PostTask(
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       FROM_HERE,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       base::Bind(&SyncNonUIDataTypeControllerTest::SignalDone,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  &done));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done.TimedWait(TestTimeouts::action_timeout());
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!done.IsSignaled()) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE() << "Timed out waiting for DB thread to finish.";
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->RunUntilIdle();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetStartExpectations() {
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(true));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(model_load_callback_, Run(_, _));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetAssociateExpectations() {
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _, _))
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        .WillOnce(Return(true));
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        .WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_,_))
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        .WillOnce(Return(syncer::SyncError()));
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), GetSyncCount()).WillOnce(Return(0));
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void SetActivateExpectations(DataTypeController::ConfigureResult result) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(start_callback_, Run(result,_,_));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetStopExpectations() {
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), StopModels());
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*change_processor_.get(), Disconnect()).WillOnce(Return(true));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void SetStartFailExpectations(DataTypeController::ConfigureResult result) {
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), StopModels()).Times(AtLeast(1));
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*dtc_mock_.get(), RecordStartFailure(result));
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(start_callback_, Run(result, _, _));
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Start() {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    non_ui_dtc_->LoadModels(
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ModelLoadCallbackMock::Run,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(&model_load_callback_)));
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    non_ui_dtc_->StartAssociating(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&StartCallbackMock::Run,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(&start_callback_)));
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void SignalDone(WaitableEvent* done) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done->Signal();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForUI message_loop_;
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::Thread backend_thread_;
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartCallbackMock start_callback_;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModelLoadCallbackMock model_load_callback_;
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Must be destroyed after non_ui_dtc_.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::FakeSyncableService syncable_service_;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<NonUIDataTypeControllerFake> non_ui_dtc_;
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<NonUIDataTypeControllerMock> dtc_mock_;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SharedChangeProcessorMock> change_processor_;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<syncer::SyncChangeProcessor> saved_change_processor_;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StartOk) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StartFirstRun) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _, _))
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(true));
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_,_))
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(syncer::SyncError()));
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start the DTC and have StartModels() return false.  Then, stop the
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DTC without finishing model startup.  It should stop cleanly.
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, AbortDuringStartModels) {
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(false));
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), StopModels());
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->LoadModels(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ModelLoadCallbackMock::Run,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(&model_load_callback_)));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::MODEL_STARTING, non_ui_dtc_->state());
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start the DTC and have MergeDataAndStartSyncing() return an error.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The DTC should become disabled, and the DTC should still stop
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cleanly.
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StartAssociationFailed) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _, _))
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(true));
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_,_))
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(syncer::SyncError()));
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up association to fail with an association failed error.
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncable_service_.set_merge_data_and_start_syncing_error(
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncer::SyncError(FROM_HERE,
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        syncer::SyncError::DATATYPE_ERROR,
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        "Sync Error",
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        non_ui_dtc_->type()));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::DISABLED, non_ui_dtc_->state());
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
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)       StartAssociationTriggersUnrecoverableError) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up association to fail with an unrecoverable error.
357010d83a9304c5a91596085d917d248abff47903aTorne (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(true));
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       StartAssociationCryptoNotReady) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up association to fail with a NEEDS_CRYPTO error.
374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _, _))
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillRepeatedly(Return(false));
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Trigger a Stop() call when we check if the model associator has user created
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// nodes.
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, AbortDuringAssociation) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent wait_for_db_thread_pause(false, false);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent pause_db_thread(false, false);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
391010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _, _))
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(GetWeakPtrToSyncableService(&syncable_service_));
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(true));
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(DoAll(SignalEvent(&wait_for_db_thread_pause),
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      WaitOnEvent(&pause_db_thread),
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      SetArgumentPointee<0>(true),
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      Return(true)));
40058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_,_))
40158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      .WillOnce(
40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          Return(syncer::SyncError(FROM_HERE,
40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   syncer::SyncError::DATATYPE_ERROR,
40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   "Disconnected.",
40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   AUTOFILL_PROFILE)));
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Disconnect())
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(DoAll(SignalEvent(&pause_db_thread), Return(true)));
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_for_db_thread_pause.Wait();
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start the DTC while the backend tasks are blocked. Then stop the DTC before
417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the backend tasks get a chance to run.
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StartAfterSyncShutdown) {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->BlockBackendTasks();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't expect StopSyncing to be called because local_service_ will never
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have been set.
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Disconnect()).WillOnce(Return(true));
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Mock::VerifyAndClearExpectations(change_processor_.get());
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Mock::VerifyAndClearExpectations(dtc_mock_.get());
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_CALL(*change_processor_.get(), Connect(_, _, _, _, _, _))
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillOnce(Return(base::WeakPtr<syncer::SyncableService>()));
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->UnblockBackendTasks();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, Stop) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStopExpectations();
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start the DTC then block its backend tasks.  While its backend
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tasks are blocked, stop and start it again, then unblock its
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// backend tasks.  The (delayed) running of the backend tasks from the
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stop after the restart shouldn't cause any problems.
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, StopStart) {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStopExpectations();
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->BlockBackendTasks();
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->Stop();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  non_ui_dtc_->UnblockBackendTasks();
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)TEST_F(SyncNonUIDataTypeControllerTest, OnSingleDataTypeUnrecoverableError) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartExpectations();
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetAssociateExpectations();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetActivateExpectations(DataTypeController::OK);
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Start();
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
4866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  testing::Mock::VerifyAndClearExpectations(&start_callback_);
4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_CALL(model_load_callback_, Run(_, _));
4896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  syncer::SyncError error(FROM_HERE,
4906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          syncer::SyncError::DATATYPE_ERROR,
4916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          "error",
4926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          non_ui_dtc_->type());
493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  backend_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &NonUIDataTypeControllerFake::
4956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          OnSingleDataTypeUnrecoverableError,
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      non_ui_dtc_.get(),
4976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      error));
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForDTC();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace sync_driver
504