1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "testing/gtest/include/gtest/gtest.h"
6
7#include "base/callback.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/message_loop.h"
10#include "base/task.h"
11#include "chrome/browser/sync/glue/extension_data_type_controller.h"
12#include "chrome/browser/sync/glue/change_processor_mock.h"
13#include "chrome/browser/sync/glue/model_associator_mock.h"
14#include "chrome/browser/sync/profile_sync_factory_mock.h"
15#include "chrome/browser/sync/profile_sync_service_mock.h"
16#include "chrome/test/profile_mock.h"
17#include "content/browser/browser_thread.h"
18
19using browser_sync::ExtensionDataTypeController;
20using browser_sync::ChangeProcessorMock;
21using browser_sync::DataTypeController;
22using browser_sync::ModelAssociatorMock;
23using testing::_;
24using testing::DoAll;
25using testing::InvokeWithoutArgs;
26using testing::Return;
27using testing::SetArgumentPointee;
28
29class StartCallback {
30 public:
31  MOCK_METHOD2(Run, void(DataTypeController::StartResult result,
32    const tracked_objects::Location& location));
33};
34
35class ExtensionDataTypeControllerTest : public testing::Test {
36 public:
37  ExtensionDataTypeControllerTest()
38      : ui_thread_(BrowserThread::UI, &message_loop_) {}
39
40  virtual void SetUp() {
41    profile_sync_factory_.reset(new ProfileSyncFactoryMock());
42    extension_dtc_ =
43        new ExtensionDataTypeController(profile_sync_factory_.get(),
44                                        &profile_, &service_);
45  }
46
47 protected:
48  void SetStartExpectations() {
49    model_associator_ = new ModelAssociatorMock();
50    change_processor_ = new ChangeProcessorMock();
51    EXPECT_CALL(*profile_sync_factory_, CreateExtensionSyncComponents(_, _)).
52        WillOnce(Return(
53            ProfileSyncFactory::SyncComponents(model_associator_,
54                                               change_processor_)));
55  }
56
57  void SetAssociateExpectations() {
58    EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
59        WillRepeatedly(Return(true));
60    EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
61        WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true)));
62    EXPECT_CALL(*model_associator_, AssociateModels()).
63        WillRepeatedly(Return(true));
64  }
65
66  void SetActivateExpectations() {
67    EXPECT_CALL(service_, ActivateDataType(_, _));
68  }
69
70  void SetStopExpectations() {
71    EXPECT_CALL(service_, DeactivateDataType(_, _));
72    EXPECT_CALL(*model_associator_, DisassociateModels());
73  }
74
75  MessageLoopForUI message_loop_;
76  BrowserThread ui_thread_;
77  scoped_refptr<ExtensionDataTypeController> extension_dtc_;
78  scoped_ptr<ProfileSyncFactoryMock> profile_sync_factory_;
79  ProfileMock profile_;
80  ProfileSyncServiceMock service_;
81  ModelAssociatorMock* model_associator_;
82  ChangeProcessorMock* change_processor_;
83  StartCallback start_callback_;
84};
85
86TEST_F(ExtensionDataTypeControllerTest, Start) {
87  SetStartExpectations();
88  SetAssociateExpectations();
89  SetActivateExpectations();
90  EXPECT_EQ(DataTypeController::NOT_RUNNING, extension_dtc_->state());
91  EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _));
92  extension_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
93  EXPECT_EQ(DataTypeController::RUNNING, extension_dtc_->state());
94}
95
96TEST_F(ExtensionDataTypeControllerTest, StartFirstRun) {
97  SetStartExpectations();
98  SetAssociateExpectations();
99  SetActivateExpectations();
100  EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
101      WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(true)));
102  EXPECT_CALL(start_callback_, Run(DataTypeController::OK_FIRST_RUN, _));
103  extension_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
104}
105
106TEST_F(ExtensionDataTypeControllerTest, StartOk) {
107  SetStartExpectations();
108  SetAssociateExpectations();
109  SetActivateExpectations();
110  EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
111      WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true)));
112
113  EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _));
114  extension_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
115}
116
117TEST_F(ExtensionDataTypeControllerTest, StartAssociationFailed) {
118  SetStartExpectations();
119  SetAssociateExpectations();
120  EXPECT_CALL(*model_associator_, AssociateModels()).
121      WillRepeatedly(Return(false));
122
123  EXPECT_CALL(start_callback_, Run(DataTypeController::ASSOCIATION_FAILED, _));
124  extension_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
125  EXPECT_EQ(DataTypeController::NOT_RUNNING, extension_dtc_->state());
126}
127
128TEST_F(ExtensionDataTypeControllerTest,
129       StartAssociationTriggersUnrecoverableError) {
130  SetStartExpectations();
131  // Set up association to fail with an unrecoverable error.
132  EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
133      WillRepeatedly(Return(true));
134  EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
135      WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
136  EXPECT_CALL(start_callback_, Run(DataTypeController::UNRECOVERABLE_ERROR, _));
137  extension_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
138  EXPECT_EQ(DataTypeController::NOT_RUNNING, extension_dtc_->state());
139}
140
141TEST_F(ExtensionDataTypeControllerTest, Stop) {
142  SetStartExpectations();
143  SetAssociateExpectations();
144  SetActivateExpectations();
145  SetStopExpectations();
146
147  EXPECT_EQ(DataTypeController::NOT_RUNNING, extension_dtc_->state());
148
149  EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _));
150  extension_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
151  EXPECT_EQ(DataTypeController::RUNNING, extension_dtc_->state());
152  extension_dtc_->Stop();
153  EXPECT_EQ(DataTypeController::NOT_RUNNING, extension_dtc_->state());
154}
155
156// TODO(akalin): Add this test to all the other DTCs.
157TEST_F(ExtensionDataTypeControllerTest, OnUnrecoverableError) {
158  SetStartExpectations();
159  SetAssociateExpectations();
160  SetActivateExpectations();
161  EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
162      WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true)));
163  EXPECT_CALL(service_, OnUnrecoverableError(_, _)).
164      WillOnce(InvokeWithoutArgs(extension_dtc_.get(),
165                                 &ExtensionDataTypeController::Stop));
166  SetStopExpectations();
167
168  EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _));
169  extension_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
170  // This should cause extension_dtc_->Stop() to be called.
171  extension_dtc_->OnUnrecoverableError(FROM_HERE, "Test");
172}
173