Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(336)

Side by Side Diff: components/history/core/browser/history_model_worker_unittest.cc

Issue 2782573002: [Sync] Refactor ModelSafeWorker::DoWorkAndWaitUntilDone() to avoid code duplication. (Closed)
Patch Set: self-review Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 "components/history/core/browser/history_model_worker.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/macros.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/atomic_flag.h"
15 #include "base/test/test_simple_task_runner.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/threading/platform_thread.h"
18 #include "base/threading/thread.h"
19 #include "components/history/core/browser/history_db_task.h"
20 #include "components/history/core/browser/history_service.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace browser_sync {
24 namespace {
25
26 class HistoryServiceMock : public history::HistoryService {
27 public:
28 HistoryServiceMock(scoped_refptr<base::SingleThreadTaskRunner> history_thread)
29 : history_thread_(std::move(history_thread)) {}
30
31 base::CancelableTaskTracker::TaskId ScheduleDBTask(
32 std::unique_ptr<history::HistoryDBTask> task,
33 base::CancelableTaskTracker* tracker) override {
34 history::HistoryDBTask* task_raw = task.get();
35 history_thread_->PostTaskAndReply(
36 FROM_HERE,
37 base::Bind(base::IgnoreResult(&history::HistoryDBTask::RunOnDBThread),
38 base::Unretained(task_raw), nullptr, nullptr),
39 base::Bind(&history::HistoryDBTask::DoneRunOnMainThread,
40 base::Passed(std::move(task))));
41 return base::CancelableTaskTracker::kBadTaskId; // Unused.
42 }
43
44 private:
45 const scoped_refptr<base::SingleThreadTaskRunner> history_thread_;
46
47 DISALLOW_COPY_AND_ASSIGN(HistoryServiceMock);
48 };
49
50 syncer::WorkCallback ClosureToWorkCallback(base::Closure work) {
51 return base::Bind(
52 [](base::Closure work) {
53 work.Run();
54 return syncer::SYNCER_OK;
55 },
56 std::move(work));
57 }
58
59 class HistoryModelWorkerTest : public testing::Test {
60 public:
61 HistoryModelWorkerTest()
62 : sync_thread_("SyncThreadForTest"),
63 history_service_(history_thread_),
64 history_service_factory_(&history_service_) {
65 sync_thread_.Start();
66 worker_ = new HistoryModelWorker(history_service_factory_.GetWeakPtr(),
67 ui_thread_);
68 }
69
70 ~HistoryModelWorkerTest() override {
71 // HistoryModelWorker posts a cleanup task to the UI thread in its
72 // destructor. Run it to prevent a leak.
73 worker_ = nullptr;
74 ui_thread_->RunUntilIdle();
75 }
76
77 protected:
78 void DoWorkAndWaitUntilDoneOnSyncThread(base::Closure work) {
79 sync_thread_.task_runner()->PostTask(
80 FROM_HERE,
81 base::Bind(
82 base::IgnoreResult(&HistoryModelWorker::DoWorkAndWaitUntilDone),
83 worker_, base::Passed(ClosureToWorkCallback(work))));
84 sync_thread_.task_runner()->PostTask(
85 FROM_HERE, base::Bind(&base::AtomicFlag::Set,
86 base::Unretained(&sync_thread_unblocked_)));
87 }
88
89 const scoped_refptr<base::TestSimpleTaskRunner> ui_thread_ =
90 new base::TestSimpleTaskRunner();
91 scoped_refptr<base::TestSimpleTaskRunner> history_thread_ =
92 new base::TestSimpleTaskRunner();
93 base::AtomicFlag sync_thread_unblocked_;
94 base::Thread sync_thread_;
95 HistoryServiceMock history_service_;
96 scoped_refptr<HistoryModelWorker> worker_;
97
98 private:
99 base::WeakPtrFactory<HistoryServiceMock> history_service_factory_;
100
101 DISALLOW_COPY_AND_ASSIGN(HistoryModelWorkerTest);
102 };
103
104 } // namespace
105
106 TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDone) {
107 bool did_work = false;
108 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
109 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
110
111 EXPECT_FALSE(did_work);
112 EXPECT_FALSE(sync_thread_unblocked_.IsSet());
113
114 // Wait for a task to be posted to the UI thread and run it. Expect this task
115 // to post another task to the history DB thread and run it.
116 while (!ui_thread_->HasPendingTask())
117 base::PlatformThread::YieldCurrentThread();
118 ui_thread_->RunUntilIdle();
119 EXPECT_TRUE(history_thread_->HasPendingTask());
120 history_thread_->RunUntilIdle();
121
122 EXPECT_TRUE(did_work);
123
124 sync_thread_.Stop();
125 EXPECT_TRUE(sync_thread_unblocked_.IsSet());
126 }
127
128 TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDoneRequestStopBeforeRunWork) {
129 bool did_work = false;
130 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
131 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
132
133 EXPECT_FALSE(did_work);
134 EXPECT_FALSE(sync_thread_unblocked_.IsSet());
135
136 // Wait for a task to be posted to the UI thread and run it.
137 while (!ui_thread_->HasPendingTask())
138 base::PlatformThread::YieldCurrentThread();
139 ui_thread_->RunUntilIdle();
140
141 // Stop the worker.
142 worker_->RequestStop();
143
144 // The WorkCallback should not run on the history DB thread.
145 EXPECT_TRUE(history_thread_->HasPendingTask());
146 history_thread_->RunUntilIdle();
147 EXPECT_FALSE(did_work);
148
149 sync_thread_.Stop();
150 EXPECT_TRUE(sync_thread_unblocked_.IsSet());
151 }
152
153 TEST_F(HistoryModelWorkerTest,
154 DoWorkAndWaitUntilDoneRequestStopBeforeUITaskRun) {
155 bool did_work = false;
156 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
157 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
158
159 EXPECT_FALSE(did_work);
160 EXPECT_FALSE(sync_thread_unblocked_.IsSet());
161
162 // Wait for a task to be posted to the UI thread.
163 while (!ui_thread_->HasPendingTask())
164 base::PlatformThread::YieldCurrentThread();
165
166 // Stop the worker.
167 worker_->RequestStop();
168
169 // Stopping the worker should unblock the sync thread.
170 sync_thread_.Stop();
171 EXPECT_TRUE(sync_thread_unblocked_.IsSet());
172 }
173
174 TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDoneDeleteWorkBeforeRun) {
175 bool did_work = false;
176 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
177 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
178
179 EXPECT_FALSE(did_work);
180 EXPECT_FALSE(sync_thread_unblocked_.IsSet());
181
182 // Wait for a task to be posted to the UI thread. Delete it before it can run.
183 while (!ui_thread_->HasPendingTask())
184 base::PlatformThread::YieldCurrentThread();
185 ui_thread_->ClearPendingTasks();
186
187 EXPECT_FALSE(did_work);
188
189 // Deleting the task should have unblocked the sync thread.
190 sync_thread_.Stop();
191 EXPECT_TRUE(sync_thread_unblocked_.IsSet());
192 }
193
194 TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDoneRequestStopDuringRunWork) {
195 bool did_work = false;
196 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
197 [](scoped_refptr<HistoryModelWorker> worker,
198 base::AtomicFlag* sync_thread_unblocked, bool* did_work) {
199 worker->RequestStop();
200 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
201
202 // The sync thread should not be unblocked while a WorkCallback is
203 // running.
204 EXPECT_FALSE(sync_thread_unblocked->IsSet());
205
206 *did_work = true;
207 },
208 worker_, base::Unretained(&sync_thread_unblocked_),
209 base::Unretained(&did_work)));
210 EXPECT_FALSE(did_work);
211 EXPECT_FALSE(sync_thread_unblocked_.IsSet());
212
213 // Wait for a task to be posted to the UI thread and run it.
214 while (!ui_thread_->HasPendingTask())
215 base::PlatformThread::YieldCurrentThread();
216 ui_thread_->RunUntilIdle();
217
218 // Expect a task to be posted to the history DB thread. Run it.
219 EXPECT_TRUE(history_thread_->HasPendingTask());
220 history_thread_->RunUntilIdle();
221 EXPECT_TRUE(did_work);
222
223 sync_thread_.Stop();
224 EXPECT_TRUE(sync_thread_unblocked_.IsSet());
225 }
226
227 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698