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