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 virtual void DoWork() OVERRIDE { 25 ASSERT_TRUE(test_); 26 test_->OnWork(); 27 } 28 virtual void OnWorkFinished() OVERRIDE { 29 ASSERT_TRUE(test_); 30 test_->OnWorkFinished(); 31 } 32 private: 33 virtual ~TestSerialWorker() {} 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 virtual void SetUp() OVERRIDE { 100 message_loop_ = base::MessageLoop::current(); 101 worker_ = new TestSerialWorker(this); 102 } 103 104 virtual 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 164