OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/sync/engine/model_safe_worker.h" | 5 #include "components/sync/engine/model_safe_worker.h" |
6 | 6 |
7 #include <utility> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/macros.h" | |
11 #include "base/synchronization/atomic_flag.h" | |
12 #include "base/test/test_simple_task_runner.h" | |
13 #include "base/test/test_timeouts.h" | |
14 #include "base/threading/platform_thread.h" | |
15 #include "base/threading/thread.h" | |
16 #include "base/values.h" | 7 #include "base/values.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
18 | 9 |
19 namespace syncer { | 10 namespace syncer { |
20 namespace { | 11 namespace { |
21 | 12 |
22 syncer::WorkCallback ClosureToWorkCallback(base::Closure work) { | 13 class ModelSafeWorkerTest : public ::testing::Test {}; |
23 return base::Bind( | |
24 [](base::Closure work) { | |
25 work.Run(); | |
26 return syncer::SYNCER_OK; | |
27 }, | |
28 std::move(work)); | |
29 } | |
30 | |
31 class MockModelSafeWorker : public ModelSafeWorker { | |
32 public: | |
33 MockModelSafeWorker() = default; | |
34 | |
35 void ScheduleWork(base::OnceClosure work) override { | |
36 task_runner_->PostTask(FROM_HERE, std::move(work)); | |
37 } | |
38 | |
39 ModelSafeGroup GetModelSafeGroup() override { return GROUP_PASSIVE; } | |
40 | |
41 bool IsOnModelThread() override { | |
42 return task_runner_->BelongsToCurrentThread(); | |
43 } | |
44 | |
45 scoped_refptr<base::TestSimpleTaskRunner> task_runner() const { | |
46 return task_runner_; | |
47 } | |
48 | |
49 private: | |
50 friend class base::RefCountedThreadSafe<MockModelSafeWorker>; | |
51 | |
52 ~MockModelSafeWorker() override = default; | |
53 | |
54 const scoped_refptr<base::TestSimpleTaskRunner> task_runner_ = | |
55 new base::TestSimpleTaskRunner(); | |
56 | |
57 DISALLOW_COPY_AND_ASSIGN(MockModelSafeWorker); | |
58 }; | |
59 | |
60 class ModelSafeWorkerTest : public ::testing::Test { | |
61 protected: | |
62 ModelSafeWorkerTest() : sync_thread_("SyncThreadForTest") { | |
63 sync_thread_.Start(); | |
64 } | |
65 | |
66 void DoWorkAndWaitUntilDoneOnSyncThread(base::Closure work) { | |
67 sync_thread_.task_runner()->PostTask( | |
68 FROM_HERE, | |
69 base::Bind(base::IgnoreResult(&ModelSafeWorker::DoWorkAndWaitUntilDone), | |
70 worker_, base::Passed(ClosureToWorkCallback(work)))); | |
71 sync_thread_.task_runner()->PostTask( | |
72 FROM_HERE, base::Bind(&base::AtomicFlag::Set, | |
73 base::Unretained(&sync_thread_unblocked_))); | |
74 } | |
75 | |
76 base::AtomicFlag sync_thread_unblocked_; | |
77 base::Thread sync_thread_; | |
78 const scoped_refptr<MockModelSafeWorker> worker_ = new MockModelSafeWorker(); | |
79 | |
80 private: | |
81 DISALLOW_COPY_AND_ASSIGN(ModelSafeWorkerTest); | |
82 }; | |
83 | |
84 } // namespace | |
85 | 14 |
86 TEST_F(ModelSafeWorkerTest, ModelSafeRoutingInfoToValue) { | 15 TEST_F(ModelSafeWorkerTest, ModelSafeRoutingInfoToValue) { |
87 ModelSafeRoutingInfo routing_info; | 16 ModelSafeRoutingInfo routing_info; |
88 routing_info[BOOKMARKS] = GROUP_PASSIVE; | 17 routing_info[BOOKMARKS] = GROUP_PASSIVE; |
89 routing_info[NIGORI] = GROUP_UI; | 18 routing_info[NIGORI] = GROUP_UI; |
90 routing_info[PREFERENCES] = GROUP_DB; | 19 routing_info[PREFERENCES] = GROUP_DB; |
91 routing_info[APPS] = GROUP_NON_BLOCKING; | 20 routing_info[APPS] = GROUP_NON_BLOCKING; |
92 base::DictionaryValue expected_value; | 21 base::DictionaryValue expected_value; |
93 expected_value.SetString("Apps", "GROUP_NON_BLOCKING"); | 22 expected_value.SetString("Apps", "GROUP_NON_BLOCKING"); |
94 expected_value.SetString("Bookmarks", "GROUP_PASSIVE"); | 23 expected_value.SetString("Bookmarks", "GROUP_PASSIVE"); |
(...skipping 18 matching lines...) Expand all Loading... |
113 | 42 |
114 TEST_F(ModelSafeWorkerTest, GetRoutingInfoTypes) { | 43 TEST_F(ModelSafeWorkerTest, GetRoutingInfoTypes) { |
115 ModelSafeRoutingInfo routing_info; | 44 ModelSafeRoutingInfo routing_info; |
116 routing_info[BOOKMARKS] = GROUP_PASSIVE; | 45 routing_info[BOOKMARKS] = GROUP_PASSIVE; |
117 routing_info[NIGORI] = GROUP_UI; | 46 routing_info[NIGORI] = GROUP_UI; |
118 routing_info[PREFERENCES] = GROUP_DB; | 47 routing_info[PREFERENCES] = GROUP_DB; |
119 const ModelTypeSet expected_types(BOOKMARKS, NIGORI, PREFERENCES); | 48 const ModelTypeSet expected_types(BOOKMARKS, NIGORI, PREFERENCES); |
120 EXPECT_EQ(expected_types, GetRoutingInfoTypes(routing_info)); | 49 EXPECT_EQ(expected_types, GetRoutingInfoTypes(routing_info)); |
121 } | 50 } |
122 | 51 |
123 TEST_F(ModelSafeWorkerTest, DoWorkAndWaitUntilDone) { | 52 } // namespace |
124 bool did_work = false; | |
125 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind( | |
126 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work))); | |
127 | |
128 EXPECT_FALSE(did_work); | |
129 EXPECT_FALSE(sync_thread_unblocked_.IsSet()); | |
130 | |
131 // Wait for a task to be posted to |worker_|'s TaskRunner and run it. | |
132 while (!worker_->task_runner()->HasPendingTask()) | |
133 base::PlatformThread::YieldCurrentThread(); | |
134 worker_->task_runner()->RunUntilIdle(); | |
135 | |
136 EXPECT_TRUE(did_work); | |
137 | |
138 sync_thread_.Stop(); | |
139 EXPECT_TRUE(sync_thread_unblocked_.IsSet()); | |
140 } | |
141 | |
142 TEST_F(ModelSafeWorkerTest, DoWorkAndWaitUntilDoneRequestStopBeforeRunWork) { | |
143 bool did_work = false; | |
144 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind( | |
145 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work))); | |
146 | |
147 EXPECT_FALSE(did_work); | |
148 EXPECT_FALSE(sync_thread_unblocked_.IsSet()); | |
149 | |
150 // Wait for a task to be posted to |worker_|'s TaskRunner. | |
151 while (!worker_->task_runner()->HasPendingTask()) | |
152 base::PlatformThread::YieldCurrentThread(); | |
153 | |
154 // Stop the worker. | |
155 worker_->RequestStop(); | |
156 | |
157 // The WorkCallback should not run. | |
158 worker_->task_runner()->RunUntilIdle(); | |
159 EXPECT_FALSE(did_work); | |
160 | |
161 sync_thread_.Stop(); | |
162 EXPECT_TRUE(sync_thread_unblocked_.IsSet()); | |
163 } | |
164 | |
165 TEST_F(ModelSafeWorkerTest, DoWorkAndWaitUntilDoneDeleteWorkBeforeRun) { | |
166 bool did_work = false; | |
167 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind( | |
168 [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work))); | |
169 | |
170 EXPECT_FALSE(did_work); | |
171 EXPECT_FALSE(sync_thread_unblocked_.IsSet()); | |
172 | |
173 // Wait for a task to be posted to |worker_|'s TaskRunner and delete it. | |
174 while (!worker_->task_runner()->HasPendingTask()) | |
175 base::PlatformThread::YieldCurrentThread(); | |
176 worker_->task_runner()->ClearPendingTasks(); | |
177 | |
178 EXPECT_FALSE(did_work); | |
179 | |
180 // Deleting the task should have unblocked the sync thread. | |
181 sync_thread_.Stop(); | |
182 EXPECT_TRUE(sync_thread_unblocked_.IsSet()); | |
183 } | |
184 | |
185 TEST_F(ModelSafeWorkerTest, DoWorkAndWaitUntilDoneRequestStopDuringRunWork) { | |
186 bool did_work = false; | |
187 DoWorkAndWaitUntilDoneOnSyncThread(base::Bind( | |
188 [](scoped_refptr<ModelSafeWorker> worker, | |
189 base::AtomicFlag* sync_thread_unblocked, bool* did_work) { | |
190 worker->RequestStop(); | |
191 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | |
192 | |
193 // The sync thread should not be unblocked while a WorkCallback is | |
194 // running. | |
195 EXPECT_FALSE(sync_thread_unblocked->IsSet()); | |
196 | |
197 *did_work = true; | |
198 }, | |
199 worker_, base::Unretained(&sync_thread_unblocked_), | |
200 base::Unretained(&did_work))); | |
201 EXPECT_FALSE(did_work); | |
202 EXPECT_FALSE(sync_thread_unblocked_.IsSet()); | |
203 | |
204 // Wait for a task to be posted to |worker_|'s TaskRunner and run it. | |
205 while (!worker_->task_runner()->HasPendingTask()) | |
206 base::PlatformThread::YieldCurrentThread(); | |
207 worker_->task_runner()->RunUntilIdle(); | |
208 | |
209 EXPECT_TRUE(did_work); | |
210 sync_thread_.Stop(); | |
211 EXPECT_TRUE(sync_thread_unblocked_.IsSet()); | |
212 } | |
213 | |
214 } // namespace syncer | 53 } // namespace syncer |
OLD | NEW |