blob: de16228fd185ee21ef59b2600e46f950aa075075 [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:
dchengb03027d2014-10-21 12:00:2036 ~TestSerialWorker() override {}
[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;
Gabriel Charette53a9ef812017-07-26 12:36:2373 base::RunLoop::QuitCurrentDeprecated();
[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) {
fdoray5eeb7642016-06-22 16:11:2883 base::RunLoop().Run();
[email protected]76d7f722011-10-10 17:22:4184 ASSERT_EQ(breakpoint_, b);
85 }
86
87 SerialWorkerTest()
88 : input_value_(0),
89 output_value_(-1),
gab07efd102016-06-02 13:33:1790 work_allowed_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
91 base::WaitableEvent::InitialState::NOT_SIGNALED),
92 work_called_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
93 base::WaitableEvent::InitialState::NOT_SIGNALED),
94 work_running_(false) {}
[email protected]76d7f722011-10-10 17:22:4195
96 // Helpers for tests.
97
98 // Lets OnWork run and waits for it to complete. Can only return if OnWork is
99 // executed on a concurrent thread.
100 void WaitForWork() {
101 RunUntilBreak("OnWork");
102 work_allowed_.Signal();
103 work_called_.Wait();
104 }
105
106 // test::Test methods
dcheng67be2b1f2014-10-27 21:47:29107 void SetUp() override {
[email protected]2da659e2013-05-23 20:51:34108 message_loop_ = base::MessageLoop::current();
[email protected]76d7f722011-10-10 17:22:41109 worker_ = new TestSerialWorker(this);
110 }
111
dcheng67be2b1f2014-10-27 21:47:29112 void TearDown() override {
[email protected]76d7f722011-10-10 17:22:41113 // Cancel the worker to catch if it makes a late DoWork call.
114 worker_->Cancel();
115 // Check if OnWork is stalled.
116 EXPECT_FALSE(work_running_) << "OnWork should be done by TearDown";
117 // Release it for cleanliness.
118 if (work_running_) {
119 WaitForWork();
120 }
121 }
122
123 // Input value read on WorkerPool.
124 int input_value_;
125 // Output value written on WorkerPool.
126 int output_value_;
127
128 // read is called on WorkerPool so we need to synchronize with it.
129 base::WaitableEvent work_allowed_;
130 base::WaitableEvent work_called_;
131
132 // Protected by read_lock_. Used to verify that read calls are serialized.
133 bool work_running_;
134 base::Lock work_lock_;
135
136 // Loop for this thread.
[email protected]2da659e2013-05-23 20:51:34137 base::MessageLoop* message_loop_;
[email protected]76d7f722011-10-10 17:22:41138
139 // WatcherDelegate under test.
140 scoped_refptr<TestSerialWorker> worker_;
141
142 std::string breakpoint_;
143};
144
145TEST_F(SerialWorkerTest, ExecuteAndSerializeReads) {
146 for (int i = 0; i < 3; ++i) {
147 ++input_value_;
148 worker_->WorkNow();
149 WaitForWork();
150 RunUntilBreak("OnWorkFinished");
151
[email protected]54aa4f12013-07-22 22:24:13152 EXPECT_TRUE(message_loop_->IsIdleForTesting());
[email protected]76d7f722011-10-10 17:22:41153 }
154
155 // Schedule two calls. OnWork checks if it is called serially.
156 ++input_value_;
157 worker_->WorkNow();
158 // read is blocked, so this will have to induce re-work
159 worker_->WorkNow();
160 WaitForWork();
161 WaitForWork();
162 RunUntilBreak("OnWorkFinished");
163
164 // No more tasks should remain.
[email protected]54aa4f12013-07-22 22:24:13165 EXPECT_TRUE(message_loop_->IsIdleForTesting());
[email protected]76d7f722011-10-10 17:22:41166}
167
168} // namespace
169
170} // namespace net