blob: d7ce1f8fc232130b5d0408bc8916890b6943d729 [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"
Gabriel Charette1e5bed442018-04-24 23:25:499#include "base/message_loop/message_loop_current.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"
Alexander Timin35cc3302018-10-31 18:54:4915#include "base/threading/thread_task_runner_handle.h"
Gabriel Charettec7108742019-08-23 03:31:4016#include "net/test/test_with_task_environment.h"
[email protected]76d7f722011-10-10 17:22:4117#include "testing/gtest/include/gtest/gtest.h"
18
19namespace net {
20
21namespace {
22
Gabriel Charette694c3c332019-08-19 14:53:0523class SerialWorkerTest : public TestWithTaskEnvironment {
[email protected]76d7f722011-10-10 17:22:4124 public:
25 // The class under test
26 class TestSerialWorker : public SerialWorker {
27 public:
Francois Doraybecd1ef72017-09-25 20:58:4528 explicit TestSerialWorker(SerialWorkerTest* t) : test_(t) {}
dchengb03027d2014-10-21 12:00:2029 void DoWork() override {
[email protected]76d7f722011-10-10 17:22:4130 ASSERT_TRUE(test_);
31 test_->OnWork();
32 }
dchengb03027d2014-10-21 12:00:2033 void OnWorkFinished() override {
[email protected]76d7f722011-10-10 17:22:4134 ASSERT_TRUE(test_);
35 test_->OnWorkFinished();
36 }
37 private:
Chris Watkins68b15032017-12-01 03:07:1338 ~TestSerialWorker() override = default;
[email protected]76d7f722011-10-10 17:22:4139 SerialWorkerTest* test_;
40 };
41
42 // Mocks
43
44 void OnWork() {
45 { // Check that OnWork is executed serially.
46 base::AutoLock lock(work_lock_);
47 EXPECT_FALSE(work_running_) << "DoRead is not called serially!";
48 work_running_ = true;
49 }
50 BreakNow("OnWork");
Francois Doraybecd1ef72017-09-25 20:58:4551 {
52 base::ScopedAllowBaseSyncPrimitivesForTesting
53 scoped_allow_base_sync_primitives;
54 work_allowed_.Wait();
55 }
Gabriel Charette52fa3ae2019-04-15 21:44:3756 // Calling from ThreadPool, but protected by work_allowed_/work_called_.
[email protected]76d7f722011-10-10 17:22:4157 output_value_ = input_value_;
58
59 { // This lock might be destroyed after work_called_ is signalled.
60 base::AutoLock lock(work_lock_);
61 work_running_ = false;
62 }
63 work_called_.Signal();
64 }
65
66 void OnWorkFinished() {
Alexander Timin35cc3302018-10-31 18:54:4967 EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
[email protected]76d7f722011-10-10 17:22:4168 EXPECT_EQ(output_value_, input_value_);
69 BreakNow("OnWorkFinished");
70 }
71
72 protected:
ki.stfu144dce12015-09-22 01:07:5773 void BreakCallback(const std::string& breakpoint) {
[email protected]221c035c2011-11-30 06:37:4074 breakpoint_ = breakpoint;
Wez61223612018-01-04 17:36:1775 run_loop_->Quit();
[email protected]221c035c2011-11-30 06:37:4076 }
[email protected]76d7f722011-10-10 17:22:4177
ki.stfu144dce12015-09-22 01:07:5778 void BreakNow(const std::string& b) {
Alexander Timin35cc3302018-10-31 18:54:4979 task_runner_->PostTask(FROM_HERE,
kylecharf4fe5172019-02-15 18:53:4980 base::BindOnce(&SerialWorkerTest::BreakCallback,
81 base::Unretained(this), b));
[email protected]76d7f722011-10-10 17:22:4182 }
83
ki.stfu144dce12015-09-22 01:07:5784 void RunUntilBreak(const std::string& b) {
Wez61223612018-01-04 17:36:1785 base::RunLoop run_loop;
86 ASSERT_FALSE(run_loop_);
87 run_loop_ = &run_loop;
88 run_loop_->Run();
89 run_loop_ = nullptr;
[email protected]76d7f722011-10-10 17:22:4190 ASSERT_EQ(breakpoint_, b);
91 }
92
93 SerialWorkerTest()
94 : input_value_(0),
95 output_value_(-1),
gab07efd102016-06-02 13:33:1796 work_allowed_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
97 base::WaitableEvent::InitialState::NOT_SIGNALED),
98 work_called_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
99 base::WaitableEvent::InitialState::NOT_SIGNALED),
100 work_running_(false) {}
[email protected]76d7f722011-10-10 17:22:41101
102 // Helpers for tests.
103
104 // Lets OnWork run and waits for it to complete. Can only return if OnWork is
105 // executed on a concurrent thread.
106 void WaitForWork() {
107 RunUntilBreak("OnWork");
108 work_allowed_.Signal();
109 work_called_.Wait();
110 }
111
112 // test::Test methods
dcheng67be2b1f2014-10-27 21:47:29113 void SetUp() override {
Alexander Timin35cc3302018-10-31 18:54:49114 task_runner_ = base::ThreadTaskRunnerHandle::Get();
[email protected]76d7f722011-10-10 17:22:41115 worker_ = new TestSerialWorker(this);
116 }
117
dcheng67be2b1f2014-10-27 21:47:29118 void TearDown() override {
[email protected]76d7f722011-10-10 17:22:41119 // Cancel the worker to catch if it makes a late DoWork call.
120 worker_->Cancel();
121 // Check if OnWork is stalled.
122 EXPECT_FALSE(work_running_) << "OnWork should be done by TearDown";
123 // Release it for cleanliness.
124 if (work_running_) {
125 WaitForWork();
126 }
127 }
128
129 // Input value read on WorkerPool.
130 int input_value_;
131 // Output value written on WorkerPool.
132 int output_value_;
133
134 // read is called on WorkerPool so we need to synchronize with it.
135 base::WaitableEvent work_allowed_;
136 base::WaitableEvent work_called_;
137
138 // Protected by read_lock_. Used to verify that read calls are serialized.
139 bool work_running_;
140 base::Lock work_lock_;
141
Alexander Timin35cc3302018-10-31 18:54:49142 // Task runner for this thread.
143 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
[email protected]76d7f722011-10-10 17:22:41144
145 // WatcherDelegate under test.
146 scoped_refptr<TestSerialWorker> worker_;
147
148 std::string breakpoint_;
Wez61223612018-01-04 17:36:17149 base::RunLoop* run_loop_ = nullptr;
150
151 DISALLOW_COPY_AND_ASSIGN(SerialWorkerTest);
[email protected]76d7f722011-10-10 17:22:41152};
153
154TEST_F(SerialWorkerTest, ExecuteAndSerializeReads) {
155 for (int i = 0; i < 3; ++i) {
156 ++input_value_;
157 worker_->WorkNow();
158 WaitForWork();
159 RunUntilBreak("OnWorkFinished");
160
Alexander Timin35cc3302018-10-31 18:54:49161 EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
[email protected]76d7f722011-10-10 17:22:41162 }
163
164 // Schedule two calls. OnWork checks if it is called serially.
165 ++input_value_;
166 worker_->WorkNow();
167 // read is blocked, so this will have to induce re-work
168 worker_->WorkNow();
169 WaitForWork();
170 WaitForWork();
171 RunUntilBreak("OnWorkFinished");
172
173 // No more tasks should remain.
Alexander Timin35cc3302018-10-31 18:54:49174 EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
[email protected]76d7f722011-10-10 17:22:41175}
176
177} // namespace
178
179} // namespace net