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

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: fix-test-error 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, base::Bind(base::IgnoreResult(
81 &HistoryModelWorker::DoWorkAndWaitUntilDone),
82 worker_, ClosureToWorkCallback(work)));
83 sync_thread_.task_runner()->PostTask(
84 FROM_HERE, base::Bind(&base::AtomicFlag::Set,
85 base::Unretained(&sync_thread_unblocked_)));
86 }
87
88 const scoped_refptr<base::TestSimpleTaskRunner> ui_thread_ =
89 new base::TestSimpleTaskRunner();
90 scoped_refptr<base::TestSimpleTaskRunner> history_thread_ =
91 new base::TestSimpleTaskRunner();
92 base::AtomicFlag sync_thread_unblocked_;
93 base::Thread sync_thread_;
94 HistoryServiceMock history_service_;
95 scoped_refptr<HistoryModelWorker> worker_;
96
97 private:
98 base::WeakPtrFactory<HistoryServiceMock> history_service_factory_;
99
100 DISALLOW_COPY_AND_ASSIGN(HistoryModelWorkerTest);
101 };
102
103 } // namespace
104
105 TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDone) {
106 bool did_work = false;
107 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
108 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
109
110 EXPECT_FALSE(did_work);
111 EXPECT_FALSE(sync_thread_unblocked_.IsSet());
112
113 // Wait for a task to be posted to the UI thread and run it. Expect this task
114 // to post another task to the history DB thread and run it.
115 while (!ui_thread_->HasPendingTask())
116 base::PlatformThread::YieldCurrentThread();
117 ui_thread_->RunUntilIdle();
118 EXPECT_TRUE(history_thread_->HasPendingTask());
119 history_thread_->RunUntilIdle();
120
121 EXPECT_TRUE(did_work);
122
123 sync_thread_.Stop();
124 EXPECT_TRUE(sync_thread_unblocked_.IsSet());
125 }
126
127 TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDoneRequestStopBeforeRunWork) {
128 bool did_work = false;
129 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
130 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
131
132 EXPECT_FALSE(did_work);
133 EXPECT_FALSE(sync_thread_unblocked_.IsSet());
134
135 // Wait for a task to be posted to the UI thread and run it.
136 while (!ui_thread_->HasPendingTask())
137 base::PlatformThread::YieldCurrentThread();
138 ui_thread_->RunUntilIdle();
139
140 // Stop the worker.
141 worker_->RequestStop();
142
143 // The WorkCallback should not run on the history DB thread.
144 EXPECT_TRUE(history_thread_->HasPendingTask());
145 history_thread_->RunUntilIdle();
146 EXPECT_FALSE(did_work);
147
148 sync_thread_.Stop();
149 EXPECT_TRUE(sync_thread_unblocked_.IsSet());
150 }
151
152 TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDoneDeleteWorkBeforeRun) {
153 bool did_work = false;
154 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
155 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
156
157 EXPECT_FALSE(did_work);
158 EXPECT_FALSE(sync_thread_unblocked_.IsSet());
159
160 // Wait for a task to be posted to the UI thread. Delete it before it can run.
161 while (!ui_thread_->HasPendingTask())
162 base::PlatformThread::YieldCurrentThread();
163 ui_thread_->ClearPendingTasks();
164
165 EXPECT_FALSE(did_work);
166
167 // Deleting the task should have unblocked the sync thread.
168 sync_thread_.Stop();
169 EXPECT_TRUE(sync_thread_unblocked_.IsSet());
170 }
171
172 TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDoneRequestStopDuringRunWork) {
173 bool did_work = false;
174 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
175 [](scoped_refptr<HistoryModelWorker> worker,
176 base::AtomicFlag* sync_thread_unblocked, bool* did_work) {
177 worker->RequestStop();
178 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
179
180 // The sync thread should not be unblocked while a WorkCallback is
181 // running.
182 EXPECT_FALSE(sync_thread_unblocked->IsSet());
183
184 *did_work = true;
185 },
186 worker_, base::Unretained(&sync_thread_unblocked_),
187 base::Unretained(&did_work)));
188 EXPECT_FALSE(did_work);
189 EXPECT_FALSE(sync_thread_unblocked_.IsSet());
190
191 // Wait for a task to be posted to the UI thread and run it.
192 while (!ui_thread_->HasPendingTask())
193 base::PlatformThread::YieldCurrentThread();
194 ui_thread_->RunUntilIdle();
195
196 // Expect a task to be posted to the history DB thread. Run it.
197 EXPECT_TRUE(history_thread_->HasPendingTask());
198 history_thread_->RunUntilIdle();
199 EXPECT_TRUE(did_work);
200
201 sync_thread_.Stop();
202 EXPECT_TRUE(sync_thread_unblocked_.IsSet());
203 }
204
205 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698