OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "net/dns/serial_worker.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "base/synchronization/lock.h" | |
10 #include "base/synchronization/waitable_event.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 | |
13 namespace net { | |
14 | |
15 namespace { | |
16 | |
17 class SerialWorkerTest : public testing::Test { | |
18 public: | |
19 // The class under test | |
20 class TestSerialWorker : public SerialWorker { | |
21 public: | |
22 explicit TestSerialWorker(SerialWorkerTest* t) | |
23 : test_(t) {} | |
24 void DoWork() override { | |
25 ASSERT_TRUE(test_); | |
26 test_->OnWork(); | |
27 } | |
28 void OnWorkFinished() override { | |
29 ASSERT_TRUE(test_); | |
30 test_->OnWorkFinished(); | |
31 } | |
32 private: | |
33 ~TestSerialWorker() override {} | |
34 SerialWorkerTest* test_; | |
35 }; | |
36 | |
37 // Mocks | |
38 | |
39 void OnWork() { | |
40 { // Check that OnWork is executed serially. | |
41 base::AutoLock lock(work_lock_); | |
42 EXPECT_FALSE(work_running_) << "DoRead is not called serially!"; | |
43 work_running_ = true; | |
44 } | |
45 BreakNow("OnWork"); | |
46 work_allowed_.Wait(); | |
47 // Calling from WorkerPool, but protected by work_allowed_/work_called_. | |
48 output_value_ = input_value_; | |
49 | |
50 { // This lock might be destroyed after work_called_ is signalled. | |
51 base::AutoLock lock(work_lock_); | |
52 work_running_ = false; | |
53 } | |
54 work_called_.Signal(); | |
55 } | |
56 | |
57 void OnWorkFinished() { | |
58 EXPECT_TRUE(message_loop_ == base::MessageLoop::current()); | |
59 EXPECT_EQ(output_value_, input_value_); | |
60 BreakNow("OnWorkFinished"); | |
61 } | |
62 | |
63 protected: | |
64 void BreakCallback(std::string breakpoint) { | |
65 breakpoint_ = breakpoint; | |
66 base::MessageLoop::current()->QuitNow(); | |
67 } | |
68 | |
69 void BreakNow(std::string b) { | |
70 message_loop_->PostTask(FROM_HERE, | |
71 base::Bind(&SerialWorkerTest::BreakCallback, | |
72 base::Unretained(this), b)); | |
73 } | |
74 | |
75 void RunUntilBreak(std::string b) { | |
76 message_loop_->Run(); | |
77 ASSERT_EQ(breakpoint_, b); | |
78 } | |
79 | |
80 SerialWorkerTest() | |
81 : input_value_(0), | |
82 output_value_(-1), | |
83 work_allowed_(false, false), | |
84 work_called_(false, false), | |
85 work_running_(false) { | |
86 } | |
87 | |
88 // Helpers for tests. | |
89 | |
90 // Lets OnWork run and waits for it to complete. Can only return if OnWork is | |
91 // executed on a concurrent thread. | |
92 void WaitForWork() { | |
93 RunUntilBreak("OnWork"); | |
94 work_allowed_.Signal(); | |
95 work_called_.Wait(); | |
96 } | |
97 | |
98 // test::Test methods | |
99 void SetUp() override { | |
100 message_loop_ = base::MessageLoop::current(); | |
101 worker_ = new TestSerialWorker(this); | |
102 } | |
103 | |
104 void TearDown() override { | |
105 // Cancel the worker to catch if it makes a late DoWork call. | |
106 worker_->Cancel(); | |
107 // Check if OnWork is stalled. | |
108 EXPECT_FALSE(work_running_) << "OnWork should be done by TearDown"; | |
109 // Release it for cleanliness. | |
110 if (work_running_) { | |
111 WaitForWork(); | |
112 } | |
113 } | |
114 | |
115 // Input value read on WorkerPool. | |
116 int input_value_; | |
117 // Output value written on WorkerPool. | |
118 int output_value_; | |
119 | |
120 // read is called on WorkerPool so we need to synchronize with it. | |
121 base::WaitableEvent work_allowed_; | |
122 base::WaitableEvent work_called_; | |
123 | |
124 // Protected by read_lock_. Used to verify that read calls are serialized. | |
125 bool work_running_; | |
126 base::Lock work_lock_; | |
127 | |
128 // Loop for this thread. | |
129 base::MessageLoop* message_loop_; | |
130 | |
131 // WatcherDelegate under test. | |
132 scoped_refptr<TestSerialWorker> worker_; | |
133 | |
134 std::string breakpoint_; | |
135 }; | |
136 | |
137 TEST_F(SerialWorkerTest, ExecuteAndSerializeReads) { | |
138 for (int i = 0; i < 3; ++i) { | |
139 ++input_value_; | |
140 worker_->WorkNow(); | |
141 WaitForWork(); | |
142 RunUntilBreak("OnWorkFinished"); | |
143 | |
144 EXPECT_TRUE(message_loop_->IsIdleForTesting()); | |
145 } | |
146 | |
147 // Schedule two calls. OnWork checks if it is called serially. | |
148 ++input_value_; | |
149 worker_->WorkNow(); | |
150 // read is blocked, so this will have to induce re-work | |
151 worker_->WorkNow(); | |
152 WaitForWork(); | |
153 WaitForWork(); | |
154 RunUntilBreak("OnWorkFinished"); | |
155 | |
156 // No more tasks should remain. | |
157 EXPECT_TRUE(message_loop_->IsIdleForTesting()); | |
158 } | |
159 | |
160 } // namespace | |
161 | |
162 } // namespace net | |
163 | |
OLD | NEW |