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

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

Issue 23717047: Retry: sync: Gracefully handle early shutdown (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Renames Created 7 years, 3 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 | Annotate | Revision Log
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/synchronization/waitable_event.h"
10 #include "base/threading/thread.h"
11 #include "sync/internal_api/public/base/cancelation_observer.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace syncer {
15
16 class BlockingTask : public CancelationObserver {
17 public:
18 BlockingTask(CancelationSignal* cancel_signal);
19 virtual ~BlockingTask();
20
21 // Starts the |exec_thread_| and uses it to execute DoRun().
22 void RunAsync(base::WaitableEvent* task_done_signal);
23
24 // Blocks until canceled. Signals |task_done_signal| when finished.
25 void Run(base::WaitableEvent* task_done_signal);
26
27 // Implementation of CancelationObserver.
28 // Wakes up the thread blocked in Run().
29 virtual void OnSignalReceived() OVERRIDE;
30
31 // Checks if we ever did successfully start waiting for |event_|. Be careful
32 // with this. The flag itself is thread-unsafe, and the event that flips it
33 // is racy.
34 bool WasStarted();
35
36 private:
37 base::WaitableEvent event_;
38 base::Thread exec_thread_;
39 CancelationSignal* cancel_signal_;
40 bool was_started_;
41 };
42
43 BlockingTask::BlockingTask(CancelationSignal* cancel_signal)
44 : event_(true, false),
45 exec_thread_("BlockingTaskBackgroundThread"),
46 cancel_signal_(cancel_signal),
47 was_started_(false) { }
48
49 BlockingTask::~BlockingTask() {}
50
51 void BlockingTask::RunAsync(base::WaitableEvent* task_done_signal) {
52 exec_thread_.Start();
53 exec_thread_.message_loop()->PostTask(
54 FROM_HERE,
55 base::Bind(&BlockingTask::Run,
56 base::Unretained(this),
57 base::Unretained(task_done_signal)));
58 }
59
60 void BlockingTask::Run(base::WaitableEvent* task_done_signal) {
61 if (cancel_signal_->TryRegisterHandler(this)) {
62 DCHECK(!event_.IsSignaled());
63 was_started_ = true;
64 event_.Wait();
65 }
66 task_done_signal->Signal();
67 }
68
69 void BlockingTask::OnSignalReceived() {
70 event_.Signal();
71 }
72
73 bool BlockingTask::WasStarted() {
74 return was_started_;
75 }
76
77 class CancelationSignalTest : public ::testing::Test {
78 public:
79 CancelationSignalTest();
80 virtual ~CancelationSignalTest();
81
82 // Starts the blocking task on a background thread.
83 void StartBlockingTask();
84
85 // Cancels the blocking task.
86 void CancelBlocking();
87
88 // Verifies that the background task is not running. This could be beacause
89 // it was canceled early or because it was canceled after it was started.
90 //
91 // This method may block for a brief period of time while waiting for the
92 // background thread to make progress.
93 bool VerifyTaskDone();
94
95 // Verifies that the background task was canceled early.
96 //
97 // This method may block for a brief period of time while waiting for the
98 // background thread to make progress.
99 bool VerifyTaskNotStarted();
100
101 private:
102 base::MessageLoop main_loop_;
103
104 CancelationSignal signal_;
105 base::WaitableEvent task_done_event_;
106 BlockingTask blocking_task_;
107 };
108
109 CancelationSignalTest::CancelationSignalTest()
110 : task_done_event_(false, false), blocking_task_(&signal_) {}
111
112 CancelationSignalTest::~CancelationSignalTest() {}
113
114 void CancelationSignalTest::StartBlockingTask() {
115 blocking_task_.RunAsync(&task_done_event_);
116 }
117
118 void CancelationSignalTest::CancelBlocking() {
119 signal_.Signal();
120 }
121
122 bool CancelationSignalTest::VerifyTaskDone() {
123 // Wait until BlockingTask::Run() has finished.
124 task_done_event_.Wait();
125 return true;
126 }
127
128 bool CancelationSignalTest::VerifyTaskNotStarted() {
129 // Wait until BlockingTask::Run() has finished.
130 task_done_event_.Wait();
131
132 // Verify the background thread never started blocking.
133 return !blocking_task_.WasStarted();
134 }
135
136 class FakeCancelationObserver : public CancelationObserver {
137 virtual void OnSignalReceived() OVERRIDE { }
138 };
139
140 TEST(CancelationSignalTest_SingleThread, CheckFlags) {
141 FakeCancelationObserver observer;
142 CancelationSignal signal;
143
144 EXPECT_FALSE(signal.IsSignalled());
145 signal.Signal();
146 EXPECT_TRUE(signal.IsSignalled());
147 EXPECT_FALSE(signal.TryRegisterHandler(&observer));
148 }
149
150 // Send the cancelation signal before the task is started. This will ensure
151 // that the task will never be attempted.
152 TEST_F(CancelationSignalTest, CancelEarly) {
153 CancelBlocking();
154 StartBlockingTask();
155 EXPECT_TRUE(VerifyTaskNotStarted());
156 }
157
158 // Send the cancelation signal after the request to start the task has been
159 // posted. This is racy. The signal to stop may arrive before the signal to
160 // run the task. If that happens, we end up with another instance of the
161 // CancelEarly test defined earlier. If the signal requesting a stop arrives
162 // after the task has been started, it should end up stopping the task.
163 TEST_F(CancelationSignalTest, Cancel) {
164 StartBlockingTask();
165 CancelBlocking();
166 EXPECT_TRUE(VerifyTaskDone());
167 }
168
169 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/internal_api/public/base/cancelation_signal.cc ('k') | sync/internal_api/public/http_bridge.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698