Fix build break
[chromium-blink-merge.git] / chrome / browser / google_apis / operation_registry_unittest.cc
blob716d2ed0a36c0bb6e88aa157d94f1f5b94e76eea
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/google_apis/operation_registry.h"
7 #include "base/compiler_specific.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/message_loop.h"
10 #include "chrome/browser/google_apis/operation_registry.h"
11 #include "content/public/test/test_browser_thread.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 using testing::ElementsAre;
17 namespace google_apis {
19 namespace {
21 class MockOperation : public OperationRegistry::Operation,
22 public base::SupportsWeakPtr<MockOperation> {
23 public:
24 MockOperation(OperationRegistry* registry,
25 OperationType type,
26 const base::FilePath& path)
27 : OperationRegistry::Operation(registry, type, path) {}
29 MOCK_METHOD0(DoCancel, void());
31 // Make them public so that they can be called from test cases.
32 using OperationRegistry::Operation::NotifyStart;
33 using OperationRegistry::Operation::NotifyProgress;
34 using OperationRegistry::Operation::NotifyFinish;
35 using OperationRegistry::Operation::NotifySuspend;
36 using OperationRegistry::Operation::NotifyResume;
39 class MockUploadOperation : public MockOperation {
40 public:
41 explicit MockUploadOperation(OperationRegistry* registry)
42 : MockOperation(registry,
43 OPERATION_UPLOAD,
44 base::FilePath(FILE_PATH_LITERAL("/dummy/upload"))) {}
47 class MockDownloadOperation : public MockOperation {
48 public:
49 explicit MockDownloadOperation(OperationRegistry* registry)
50 : MockOperation(registry,
51 OPERATION_DOWNLOAD,
52 base::FilePath(FILE_PATH_LITERAL("/dummy/download"))) {}
55 class MockOtherOperation : public MockOperation {
56 public:
57 explicit MockOtherOperation(OperationRegistry* registry)
58 : MockOperation(registry,
59 OPERATION_OTHER,
60 base::FilePath(FILE_PATH_LITERAL("/dummy/other"))) {}
63 class TestObserver : public OperationRegistryObserver {
64 public:
65 virtual void OnProgressUpdate(
66 const OperationProgressStatusList& list) OVERRIDE {
67 status_ = list;
70 const OperationProgressStatusList& status() const {
71 return status_;
74 private:
75 OperationProgressStatusList status_;
78 class ProgressMatcher
79 : public ::testing::MatcherInterface<const OperationProgressStatus&> {
80 public:
81 ProgressMatcher(int64 expected_current, int64 expected_total)
82 : expected_current_(expected_current),
83 expected_total_(expected_total) {}
85 virtual bool MatchAndExplain(
86 const OperationProgressStatus& status,
87 testing::MatchResultListener* /* listener */) const OVERRIDE {
88 return status.progress_current == expected_current_ &&
89 status.progress_total == expected_total_;
92 virtual void DescribeTo(::std::ostream* os) const OVERRIDE {
93 *os << "current / total equals " << expected_current_ << " / " <<
94 expected_total_;
97 virtual void DescribeNegationTo(::std::ostream* os) const OVERRIDE {
98 *os << "current / total does not equal " << expected_current_ << " / " <<
99 expected_total_;
102 private:
103 const int64 expected_current_;
104 const int64 expected_total_;
107 testing::Matcher<const OperationProgressStatus&> Progress(
108 int64 current, int64 total) {
109 return testing::MakeMatcher(new ProgressMatcher(current, total));
112 } // namespace
114 // Pretty-prints OperationProgressStatus for testing purpose.
115 std::ostream& operator<<(std::ostream& os,
116 const OperationProgressStatus& status) {
117 return os << status.DebugString();
120 class OperationRegistryTest : public testing::Test {
121 protected:
122 OperationRegistryTest()
123 : ui_thread_(content::BrowserThread::UI, &message_loop_) {
125 MessageLoopForUI message_loop_;
126 content::TestBrowserThread ui_thread_;
129 TEST_F(OperationRegistryTest, OneSuccess) {
130 TestObserver observer;
131 OperationRegistry registry;
132 registry.DisableNotificationFrequencyControlForTest();
133 registry.AddObserver(&observer);
135 base::WeakPtr<MockOperation> op1 =
136 (new MockUploadOperation(&registry))->AsWeakPtr();
137 EXPECT_CALL(*op1, DoCancel()).Times(0);
139 EXPECT_EQ(0U, observer.status().size());
140 op1->NotifyStart();
141 EXPECT_THAT(observer.status(), ElementsAre(Progress(0, -1)));
142 op1->NotifyProgress(0, 100);
143 EXPECT_THAT(observer.status(), ElementsAre(Progress(0, 100)));
144 op1->NotifyProgress(100, 100);
145 EXPECT_THAT(observer.status(), ElementsAre(Progress(100, 100)));
146 op1->NotifyFinish(OPERATION_COMPLETED);
147 // Contains one "COMPLETED" notification.
148 EXPECT_THAT(observer.status(), ElementsAre(Progress(100, 100)));
149 // Then it is removed.
150 EXPECT_EQ(0U, registry.GetProgressStatusList().size());
151 EXPECT_EQ(NULL, op1.get()); // deleted
154 TEST_F(OperationRegistryTest, OneCancel) {
155 TestObserver observer;
156 OperationRegistry registry;
157 registry.DisableNotificationFrequencyControlForTest();
158 registry.AddObserver(&observer);
160 base::WeakPtr<MockOperation> op1 =
161 (new MockUploadOperation(&registry))->AsWeakPtr();
162 EXPECT_CALL(*op1, DoCancel());
164 EXPECT_EQ(0U, observer.status().size());
165 op1->NotifyStart();
166 EXPECT_THAT(observer.status(), ElementsAre(Progress(0, -1)));
167 op1->NotifyProgress(0, 100);
168 EXPECT_THAT(observer.status(), ElementsAre(Progress(0, 100)));
169 registry.CancelAll();
170 EXPECT_THAT(observer.status(), ElementsAre(Progress(0, 100)));
171 EXPECT_EQ(0U, registry.GetProgressStatusList().size());
172 EXPECT_EQ(NULL, op1.get()); // deleted
175 TEST_F(OperationRegistryTest, TwoSuccess) {
176 TestObserver observer;
177 OperationRegistry registry;
178 registry.DisableNotificationFrequencyControlForTest();
179 registry.AddObserver(&observer);
181 base::WeakPtr<MockOperation> op1 =
182 (new MockUploadOperation(&registry))->AsWeakPtr();
183 base::WeakPtr<MockOperation> op2 =
184 (new MockDownloadOperation(&registry))->AsWeakPtr();
185 EXPECT_CALL(*op1, DoCancel()).Times(0);
186 EXPECT_CALL(*op2, DoCancel()).Times(0);
188 EXPECT_EQ(0U, observer.status().size());
189 op1->NotifyStart();
190 op1->NotifyProgress(0, 100);
191 EXPECT_THAT(observer.status(), ElementsAre(Progress(0, 100)));
192 op2->NotifyStart();
193 op2->NotifyProgress(0, 200);
194 op1->NotifyProgress(50, 100);
195 EXPECT_THAT(observer.status(), ElementsAre(Progress(50, 100),
196 Progress(0, 200)));
197 op1->NotifyFinish(OPERATION_COMPLETED);
198 EXPECT_THAT(observer.status(), ElementsAre(Progress(50, 100),
199 Progress(0, 200)));
200 EXPECT_EQ(1U, registry.GetProgressStatusList().size());
201 op2->NotifyFinish(OPERATION_COMPLETED);
202 EXPECT_THAT(observer.status(), ElementsAre(Progress(0, 200)));
203 EXPECT_EQ(0U, registry.GetProgressStatusList().size());
204 EXPECT_EQ(NULL, op1.get()); // deleted
205 EXPECT_EQ(NULL, op2.get()); // deleted
208 TEST_F(OperationRegistryTest, ThreeCancel) {
209 TestObserver observer;
210 OperationRegistry registry;
211 registry.DisableNotificationFrequencyControlForTest();
212 registry.AddObserver(&observer);
214 base::WeakPtr<MockOperation> op1 =
215 (new MockUploadOperation(&registry))->AsWeakPtr();
216 base::WeakPtr<MockOperation> op2 =
217 (new MockDownloadOperation(&registry))->AsWeakPtr();
218 base::WeakPtr<MockOperation> op3 =
219 (new MockOtherOperation(&registry))->AsWeakPtr();
220 EXPECT_CALL(*op1, DoCancel());
221 EXPECT_CALL(*op2, DoCancel());
222 EXPECT_CALL(*op3, DoCancel());
224 EXPECT_EQ(0U, observer.status().size());
225 op1->NotifyStart();
226 EXPECT_EQ(1U, observer.status().size());
227 op2->NotifyStart();
228 EXPECT_EQ(2U, observer.status().size());
229 op3->NotifyStart();
230 EXPECT_EQ(2U, observer.status().size()); // only upload/download is reported.
231 registry.CancelAll();
232 EXPECT_EQ(1U, observer.status().size()); // holds the last one "COMPLETED"
233 EXPECT_EQ(0U, registry.GetProgressStatusList().size());
234 EXPECT_EQ(NULL, op1.get()); // deleted
235 EXPECT_EQ(NULL, op2.get()); // deleted
236 EXPECT_EQ(NULL, op3.get()); // deleted. CancelAll cares all operations.
239 TEST_F(OperationRegistryTest, RestartOperation) {
240 TestObserver observer;
241 OperationRegistry registry;
242 registry.DisableNotificationFrequencyControlForTest();
243 registry.AddObserver(&observer);
245 base::WeakPtr<MockOperation> op1 =
246 (new MockUploadOperation(&registry))->AsWeakPtr();
247 EXPECT_CALL(*op1, DoCancel()).Times(0);
249 op1->NotifyStart();
250 EXPECT_EQ(1U, registry.GetProgressStatusList().size());
251 op1->NotifyStart(); // restart
252 EXPECT_EQ(1U, registry.GetProgressStatusList().size());
253 op1->NotifyProgress(0, 200);
254 op1->NotifyFinish(OPERATION_COMPLETED);
255 EXPECT_EQ(0U, registry.GetProgressStatusList().size());
256 EXPECT_EQ(NULL, op1.get()); // deleted
260 TEST_F(OperationRegistryTest, SuspendCancel) {
261 TestObserver observer;
262 OperationRegistry registry;
263 registry.DisableNotificationFrequencyControlForTest();
264 registry.AddObserver(&observer);
266 // Suspend-then-resume is a hack in OperationRegistry to tie physically
267 // split but logically single operation (= chunked uploading split into
268 // multiple HTTP requests). When the "logically-single" operation is
269 // canceled between the two physical operations,
270 // |----op1----| CANCEL! |----op2----|
271 // the cancellation is notified to the callback function associated with
272 // op2, not op1. This is because, op1's callback is already invoked at this
273 // point to notify the completion of the physical operation. Completion
274 // callback must not be called more than once.
276 base::WeakPtr<MockOperation> op1 =
277 (new MockUploadOperation(&registry))->AsWeakPtr();
278 EXPECT_CALL(*op1, DoCancel()).Times(0);
280 op1->NotifyStart();
281 op1->NotifySuspend();
282 registry.CancelAll();
283 EXPECT_EQ(NULL, op1.get()); // deleted
285 base::WeakPtr<MockOperation> op2 =
286 (new MockUploadOperation(&registry))->AsWeakPtr();
287 EXPECT_CALL(*op2, DoCancel()).Times(1);
289 op2->NotifyResume();
290 EXPECT_EQ(NULL, op2.get()); // deleted
293 } // namespace google_apis