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

Side by Side Diff: sync/internal_api/public/base/cancelation_signal_unittest.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 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 2013 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 "sync/internal_api/public/base/cancelation_signal.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/platform_thread.h"
12 #include "base/threading/thread.h"
13 #include "base/time/time.h"
14 #include "sync/internal_api/public/base/cancelation_observer.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace syncer {
18
19 class BlockingTask : public CancelationObserver {
20 public:
21 explicit BlockingTask(CancelationSignal* cancel_signal);
22 ~BlockingTask() override;
23
24 // Starts the |exec_thread_| and uses it to execute DoRun().
25 void RunAsync(base::WaitableEvent* task_start_signal,
26 base::WaitableEvent* task_done_signal);
27
28 // Blocks until canceled. Signals |task_done_signal| when finished (either
29 // via early cancel or cancel after start). Signals |task_start_signal| if
30 // and when the task starts successfully (which will not happen if the task
31 // was cancelled early).
32 void Run(base::WaitableEvent* task_start_signal,
33 base::WaitableEvent* task_done_signal);
34
35 // Implementation of CancelationObserver.
36 // Wakes up the thread blocked in Run().
37 void OnSignalReceived() override;
38
39 // Checks if we ever did successfully start waiting for |event_|. Be careful
40 // with this. The flag itself is thread-unsafe, and the event that flips it
41 // is racy.
42 bool WasStarted();
43
44 private:
45 base::WaitableEvent event_;
46 base::Thread exec_thread_;
47 CancelationSignal* cancel_signal_;
48 bool was_started_;
49 };
50
51 BlockingTask::BlockingTask(CancelationSignal* cancel_signal)
52 : event_(base::WaitableEvent::ResetPolicy::MANUAL,
53 base::WaitableEvent::InitialState::NOT_SIGNALED),
54 exec_thread_("BlockingTaskBackgroundThread"),
55 cancel_signal_(cancel_signal),
56 was_started_(false) {}
57
58 BlockingTask::~BlockingTask() {
59 if (was_started_) {
60 cancel_signal_->UnregisterHandler(this);
61 }
62 }
63
64 void BlockingTask::RunAsync(base::WaitableEvent* task_start_signal,
65 base::WaitableEvent* task_done_signal) {
66 exec_thread_.Start();
67 exec_thread_.task_runner()->PostTask(
68 FROM_HERE, base::Bind(&BlockingTask::Run, base::Unretained(this),
69 base::Unretained(task_start_signal),
70 base::Unretained(task_done_signal)));
71 }
72
73 void BlockingTask::Run(
74 base::WaitableEvent* task_start_signal,
75 base::WaitableEvent* task_done_signal) {
76 if (cancel_signal_->TryRegisterHandler(this)) {
77 DCHECK(!event_.IsSignaled());
78 was_started_ = true;
79 task_start_signal->Signal();
80 event_.Wait();
81 }
82 task_done_signal->Signal();
83 }
84
85 void BlockingTask::OnSignalReceived() {
86 event_.Signal();
87 }
88
89 bool BlockingTask::WasStarted() {
90 return was_started_;
91 }
92
93 class CancelationSignalTest : public ::testing::Test {
94 public:
95 CancelationSignalTest();
96 ~CancelationSignalTest() override;
97
98 // Starts the blocking task on a background thread. Does not wait for the
99 // task to start.
100 void StartBlockingTaskAsync();
101
102 // Starts the blocking task on a background thread. Does not return until
103 // the task has been started.
104 void StartBlockingTaskAndWaitForItToStart();
105
106 // Cancels the blocking task.
107 void CancelBlocking();
108
109 // Verifies that the background task was canceled early.
110 //
111 // This method may block for a brief period of time while waiting for the
112 // background thread to make progress.
113 bool VerifyTaskNotStarted();
114
115 private:
116 base::MessageLoop main_loop_;
117
118 CancelationSignal signal_;
119 base::WaitableEvent task_start_event_;
120 base::WaitableEvent task_done_event_;
121 BlockingTask blocking_task_;
122 };
123
124 CancelationSignalTest::CancelationSignalTest()
125 : task_start_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
126 base::WaitableEvent::InitialState::NOT_SIGNALED),
127 task_done_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
128 base::WaitableEvent::InitialState::NOT_SIGNALED),
129 blocking_task_(&signal_) {}
130
131 CancelationSignalTest::~CancelationSignalTest() {}
132
133 void CancelationSignalTest::StartBlockingTaskAsync() {
134 blocking_task_.RunAsync(&task_start_event_, &task_done_event_);
135 }
136
137 void CancelationSignalTest::StartBlockingTaskAndWaitForItToStart() {
138 blocking_task_.RunAsync(&task_start_event_, &task_done_event_);
139 task_start_event_.Wait();
140 }
141
142 void CancelationSignalTest::CancelBlocking() {
143 signal_.Signal();
144 }
145
146 bool CancelationSignalTest::VerifyTaskNotStarted() {
147 // Wait until BlockingTask::Run() has finished.
148 task_done_event_.Wait();
149
150 // Verify the background thread never started blocking.
151 return !blocking_task_.WasStarted();
152 }
153
154 class FakeCancelationObserver : public CancelationObserver {
155 void OnSignalReceived() override {}
156 };
157
158 TEST(CancelationSignalTest_SingleThread, CheckFlags) {
159 FakeCancelationObserver observer;
160 CancelationSignal signal;
161
162 EXPECT_FALSE(signal.IsSignalled());
163 signal.Signal();
164 EXPECT_TRUE(signal.IsSignalled());
165 EXPECT_FALSE(signal.TryRegisterHandler(&observer));
166 }
167
168 // Send the cancelation signal before the task is started. This will ensure
169 // that the task will never be "started" (ie. TryRegisterHandler() will fail,
170 // so it will never start blocking on its main WaitableEvent).
171 TEST_F(CancelationSignalTest, CancelEarly) {
172 CancelBlocking();
173 StartBlockingTaskAsync();
174 EXPECT_TRUE(VerifyTaskNotStarted());
175 }
176
177 // Send the cancelation signal after the task has started running. This tests
178 // the non-early exit code path, where the task is stopped while it is in
179 // progress.
180 TEST_F(CancelationSignalTest, Cancel) {
181 StartBlockingTaskAndWaitForItToStart();
182
183 // Wait for the task to finish and let verify it has been started.
184 CancelBlocking();
185 EXPECT_FALSE(VerifyTaskNotStarted());
186 }
187
188 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/internal_api/public/base/cancelation_signal.cc ('k') | sync/internal_api/public/base/enum_set.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698