blob: fddb0cee71750023f2464d56120e0f925fb21a06 [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
[email protected]221c035c2011-11-30 06:37:407#include "base/bind.h"
skyostil4891b25b2015-06-11 11:43:458#include "base/location.h"
[email protected]5ee20982013-07-17 21:51:189#include "base/message_loop/message_loop.h"
fdoray5eeb7642016-06-22 16:11:2810#include "base/run_loop.h"
skyostil4891b25b2015-06-11 11:43:4511#include "base/single_thread_task_runner.h"
[email protected]76d7f722011-10-10 17:22:4112#include "base/synchronization/lock.h"
13#include "base/synchronization/waitable_event.h"
Francois Doraybecd1ef72017-09-25 20:58:4514#include "base/threading/thread_restrictions.h"
[email protected]76d7f722011-10-10 17:22:4115#include "testing/gtest/include/gtest/gtest.h"
16
17namespace net {
18
19namespace {
20
21class SerialWorkerTest : public testing::Test {
22 public:
23 // The class under test
24 class TestSerialWorker : public SerialWorker {
25 public:
Francois Doraybecd1ef72017-09-25 20:58:4526 explicit TestSerialWorker(SerialWorkerTest* t) : test_(t) {}
dchengb03027d2014-10-21 12:00:2027 void DoWork() override {
[email protected]76d7f722011-10-10 17:22:4128 ASSERT_TRUE(test_);
29 test_->OnWork();
30 }
dchengb03027d2014-10-21 12:00:2031 void OnWorkFinished() override {
[email protected]76d7f722011-10-10 17:22:4132 ASSERT_TRUE(test_);
33 test_->OnWorkFinished();
34 }
35 private:
Chris Watkins68b15032017-12-01 03:07:1336 ~TestSerialWorker() override = default;
[email protected]76d7f722011-10-10 17:22:4137 SerialWorkerTest* test_;
38 };
39
40 // Mocks
41
42 void OnWork() {
43 { // Check that OnWork is executed serially.
44 base::AutoLock lock(work_lock_);
45 EXPECT_FALSE(work_running_) << "DoRead is not called serially!";
46 work_running_ = true;
47 }
48 BreakNow("OnWork");
Francois Doraybecd1ef72017-09-25 20:58:4549 {
50 base::ScopedAllowBaseSyncPrimitivesForTesting
51 scoped_allow_base_sync_primitives;
52 work_allowed_.Wait();
53 }
54 // Calling from TaskScheduler, but protected by work_allowed_/work_called_.
[email protected]76d7f722011-10-10 17:22:4155 output_value_ = input_value_;
56
57 { // This lock might be destroyed after work_called_ is signalled.
58 base::AutoLock lock(work_lock_);
59 work_running_ = false;
60 }
61 work_called_.Signal();
62 }
63
64 void OnWorkFinished() {
fdoray39209962016-06-29 14:44:2965 EXPECT_TRUE(message_loop_->task_runner()->BelongsToCurrentThread());
[email protected]76d7f722011-10-10 17:22:4166 EXPECT_EQ(output_value_, input_value_);
67 BreakNow("OnWorkFinished");
68 }
69
70 protected:
ki.stfu144dce12015-09-22 01:07:5771 void BreakCallback(const std::string& breakpoint) {
[email protected]221c035c2011-11-30 06:37:4072 breakpoint_ = breakpoint;
Wez61223612018-01-04 17:36:1773 run_loop_->Quit();
[email protected]221c035c2011-11-30 06:37:4074 }
[email protected]76d7f722011-10-10 17:22:4175
ki.stfu144dce12015-09-22 01:07:5776 void BreakNow(const std::string& b) {
skyostil4891b25b2015-06-11 11:43:4577 message_loop_->task_runner()->PostTask(
78 FROM_HERE, base::Bind(&SerialWorkerTest::BreakCallback,
79 base::Unretained(this), b));
[email protected]76d7f722011-10-10 17:22:4180 }
81
ki.stfu144dce12015-09-22 01:07:5782 void RunUntilBreak(const std::string& b) {
Wez61223612018-01-04 17:36:1783 base::RunLoop run_loop;
84 ASSERT_FALSE(run_loop_);
85 run_loop_ = &run_loop;
86 run_loop_->Run();
87 run_loop_ = nullptr;
[email protected]76d7f722011-10-10 17:22:4188 ASSERT_EQ(breakpoint_, b);
89 }
90
91 SerialWorkerTest()
92 : input_value_(0),
93 output_value_(-1),
gab07efd102016-06-02 13:33:1794 work_allowed_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
95 base::WaitableEvent::InitialState::NOT_SIGNALED),
96 work_called_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
97 base::WaitableEvent::InitialState::NOT_SIGNALED),
98 work_running_(false) {}
[email protected]76d7f722011-10-10 17:22:4199
100 // Helpers for tests.
101
102 // Lets OnWork run and waits for it to complete. Can only return if OnWork is
103 // executed on a concurrent thread.
104 void WaitForWork() {
105 RunUntilBreak("OnWork");
106 work_allowed_.Signal();
107 work_called_.Wait();
108 }
109
110 // test::Test methods
dcheng67be2b1f2014-10-27 21:47:29111 void SetUp() override {
[email protected]2da659e2013-05-23 20:51:34112 message_loop_ = base::MessageLoop::current();
[email protected]76d7f722011-10-10 17:22:41113 worker_ = new TestSerialWorker(this);
114 }
115
dcheng67be2b1f2014-10-27 21:47:29116 void TearDown() override {
[email protected]76d7f722011-10-10 17:22:41117 // Cancel the worker to catch if it makes a late DoWork call.
118 worker_->Cancel();
119 // Check if OnWork is stalled.
120 EXPECT_FALSE(work_running_) << "OnWork should be done by TearDown";
121 // Release it for cleanliness.
122 if (work_running_) {
123 WaitForWork();
124 }
125 }
126
127 // Input value read on WorkerPool.
128 int input_value_;
129 // Output value written on WorkerPool.
130 int output_value_;
131
132 // read is called on WorkerPool so we need to synchronize with it.
133 base::WaitableEvent work_allowed_;
134 base::WaitableEvent work_called_;
135
136 // Protected by read_lock_. Used to verify that read calls are serialized.
137 bool work_running_;
138 base::Lock work_lock_;
139
140 // Loop for this thread.
[email protected]2da659e2013-05-23 20:51:34141 base::MessageLoop* message_loop_;
[email protected]76d7f722011-10-10 17:22:41142
143 // WatcherDelegate under test.
144 scoped_refptr<TestSerialWorker> worker_;
145
146 std::string breakpoint_;
Wez61223612018-01-04 17:36:17147 base::RunLoop* run_loop_ = nullptr;
148
149 DISALLOW_COPY_AND_ASSIGN(SerialWorkerTest);
[email protected]76d7f722011-10-10 17:22:41150};
151
152TEST_F(SerialWorkerTest, ExecuteAndSerializeReads) {
153 for (int i = 0; i < 3; ++i) {
154 ++input_value_;
155 worker_->WorkNow();
156 WaitForWork();
157 RunUntilBreak("OnWorkFinished");
158
[email protected]54aa4f12013-07-22 22:24:13159 EXPECT_TRUE(message_loop_->IsIdleForTesting());
[email protected]76d7f722011-10-10 17:22:41160 }
161
162 // Schedule two calls. OnWork checks if it is called serially.
163 ++input_value_;
164 worker_->WorkNow();
165 // read is blocked, so this will have to induce re-work
166 worker_->WorkNow();
167 WaitForWork();
168 WaitForWork();
169 RunUntilBreak("OnWorkFinished");
170
171 // No more tasks should remain.
[email protected]54aa4f12013-07-22 22:24:13172 EXPECT_TRUE(message_loop_->IsIdleForTesting());
[email protected]76d7f722011-10-10 17:22:41173}
174
175} // namespace
176
177} // namespace net