blob: c822547e5768bc5e138092e6add2267e3a3b3b42 [file] [log] [blame]
Paul Stewart75897df2011-04-27 09:05:53 -07001// Copyright (c) 2011 The Chromium OS 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
Paul Stewart75897df2011-04-27 09:05:53 -07005#include <stdint.h>
Paul Stewart75897df2011-04-27 09:05:53 -07006
Chris Masone487b8bf2011-05-13 16:27:57 -07007#include <base/callback_old.h>
Chris Masoneee929b72011-05-10 10:02:18 -07008#include <base/logging.h>
Chris Masone487b8bf2011-05-13 16:27:57 -07009#include <base/memory/ref_counted.h>
Chris Masone0e1d1042011-05-09 18:07:03 -070010#include <base/message_loop_proxy.h>
11#include <base/stringprintf.h>
Chris Masoneee929b72011-05-10 10:02:18 -070012#include <gmock/gmock.h>
Darin Petkov887f2982011-07-14 16:10:17 -070013#include <gtest/gtest.h>
Chris Masoneee929b72011-05-10 10:02:18 -070014
Darin Petkov67d8ecf2011-07-26 16:03:30 -070015#include "shill/io_handler.h"
Darin Petkov887f2982011-07-14 16:10:17 -070016#include "shill/mock_control.h"
Paul Stewart75897df2011-04-27 09:05:53 -070017#include "shill/shill_daemon.h"
Chris Masoneb9c00592011-10-06 13:10:39 -070018#include "shill/shill_test_config.h"
Paul Stewart75897df2011-04-27 09:05:53 -070019
20namespace shill {
21using ::testing::Test;
22using ::testing::_;
Chris Masone0e1d1042011-05-09 18:07:03 -070023using ::testing::Gt;
Paul Stewart75897df2011-04-27 09:05:53 -070024using ::testing::NotNull;
25using ::testing::Return;
Paul Stewart75897df2011-04-27 09:05:53 -070026using ::testing::StrictMock;
27
28class MockEventDispatchTester {
29 public:
30 explicit MockEventDispatchTester(EventDispatcher *dispatcher)
Chris Masone0e1d1042011-05-09 18:07:03 -070031 : dispatcher_(dispatcher),
32 triggered_(false),
33 callback_count_(0),
34 got_data_(false),
Paul Stewartf0aae102011-10-19 12:11:44 -070035 got_ready_(false),
Chris Masone0e1d1042011-05-09 18:07:03 -070036 data_callback_(NULL),
37 input_handler_(NULL),
38 tester_factory_(this) {
Paul Stewart75897df2011-04-27 09:05:53 -070039 }
40
Paul Stewartf0aae102011-10-19 12:11:44 -070041 void ScheduleFailSafe() {
42 // Set up a failsafe, so the test still exits even if something goes
43 // wrong. The Factory owns the RunnableMethod, but we get a pointer to it.
44 failsafe_ = tester_factory_.NewRunnableMethod(
45 &MockEventDispatchTester::StopDispatcher);
46 dispatcher_->PostDelayedTask(failsafe_, 100);
47 }
48
Chris Masone0e1d1042011-05-09 18:07:03 -070049 void ScheduleTimedTasks() {
50 dispatcher_->PostDelayedTask(
51 tester_factory_.NewRunnableMethod(&MockEventDispatchTester::Trigger),
52 10);
Paul Stewart75897df2011-04-27 09:05:53 -070053 }
54
Chris Masone0e1d1042011-05-09 18:07:03 -070055 void RescheduleUnlessTriggered() {
56 ++callback_count_;
Paul Stewart75897df2011-04-27 09:05:53 -070057 if (!triggered_) {
Chris Masone0e1d1042011-05-09 18:07:03 -070058 dispatcher_->PostTask(
59 tester_factory_.NewRunnableMethod(
60 &MockEventDispatchTester::RescheduleUnlessTriggered));
61 } else {
62 failsafe_->Cancel();
Paul Stewartf0aae102011-10-19 12:11:44 -070063 StopDispatcher();
Paul Stewart75897df2011-04-27 09:05:53 -070064 }
65 }
66
Paul Stewartf0aae102011-10-19 12:11:44 -070067 void StopDispatcher() {
Chris Masone0e1d1042011-05-09 18:07:03 -070068 dispatcher_->PostTask(new MessageLoop::QuitTask);
69 }
Paul Stewart75897df2011-04-27 09:05:53 -070070
Chris Masone0e1d1042011-05-09 18:07:03 -070071 void Trigger() {
72 LOG(INFO) << "MockEventDispatchTester handling " << callback_count_;
73 CallbackComplete(callback_count_);
74 triggered_ = true;
75 }
Paul Stewarta43d9232011-05-10 11:40:22 -070076
77 void HandleData(InputData *inputData) {
Chris Masone0e1d1042011-05-09 18:07:03 -070078 LOG(INFO) << "MockEventDispatchTester handling data len "
Paul Stewart83224402011-11-30 14:52:30 -080079 << base::StringPrintf("%zd %.*s", inputData->len,
80 static_cast<int>(inputData->len),
81 inputData->buf);
Paul Stewarta43d9232011-05-10 11:40:22 -070082 got_data_ = true;
83 IOComplete(inputData->len);
Paul Stewartf0aae102011-10-19 12:11:44 -070084 StopDispatcher();
Paul Stewarta43d9232011-05-10 11:40:22 -070085 }
Chris Masone0e1d1042011-05-09 18:07:03 -070086
Paul Stewarta43d9232011-05-10 11:40:22 -070087 bool GetData() { return got_data_; }
88
89 void ListenIO(int fd) {
Paul Stewartf0aae102011-10-19 12:11:44 -070090 data_callback_.reset(
91 NewCallback(this, &MockEventDispatchTester::HandleData));
92 input_handler_.reset(
93 dispatcher_->CreateInputHandler(fd, data_callback_.get()));
Paul Stewarta43d9232011-05-10 11:40:22 -070094 }
95
96 void StopListenIO() {
97 got_data_ = false;
Chris Masone0e1d1042011-05-09 18:07:03 -070098 input_handler_.reset(NULL);
Paul Stewarta43d9232011-05-10 11:40:22 -070099 }
100
Paul Stewartf0aae102011-10-19 12:11:44 -0700101 void HandleReady(int fd) {
102 // Stop event handling after we receive in input-ready event. We should
103 // no longer be called until events are re-enabled.
104 input_handler_->Stop();
105
106 if (got_ready_) {
107 // If we're still getting events after we have stopped them, something
108 // is really wrong, and we cannot just depend on ASSERT_FALSE() to get
109 // us out of it. Make sure the dispatcher is also stopped, or else we
110 // could end up never exiting.
111 StopDispatcher();
112 ASSERT_FALSE(got_ready_) << "failed to stop Input Ready events";
113 }
114 got_ready_ = true;
115
116 LOG(INFO) << "MockEventDispatchTester handling ready for fd " << fd;
117 IOComplete(callback_count_);
118
119 if (callback_count_) {
120 StopDispatcher();
121 } else {
122 // Restart Ready events after 10 millisecond delay.
123 callback_count_++;
124 dispatcher_->PostDelayedTask(tester_factory_.NewRunnableMethod(
125 &MockEventDispatchTester::RestartReady), 10);
126 }
127 }
128
129 void RestartReady() {
130 got_ready_ = false;
131 input_handler_->Start();
132 }
133
134 void ListenReady(int fd) {
135 ready_callback_.reset(
136 NewCallback(this, &MockEventDispatchTester::HandleReady));
137 input_handler_.reset(
138 dispatcher_->CreateReadyHandler(fd, IOHandler::kModeInput,
139 ready_callback_.get()));
140 }
141
142 void StopListenReady() {
143 got_ready_ = false;
144 input_handler_.reset(NULL);
145 }
146
Paul Stewart75897df2011-04-27 09:05:53 -0700147 MOCK_METHOD1(CallbackComplete, void(int));
Paul Stewarta43d9232011-05-10 11:40:22 -0700148 MOCK_METHOD1(IOComplete, void(int));
Paul Stewart26b327e2011-10-19 11:38:09 -0700149
Paul Stewart75897df2011-04-27 09:05:53 -0700150 private:
Paul Stewarta43d9232011-05-10 11:40:22 -0700151 EventDispatcher *dispatcher_;
Paul Stewart75897df2011-04-27 09:05:53 -0700152 bool triggered_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700153 int callback_count_;
Paul Stewarta43d9232011-05-10 11:40:22 -0700154 bool got_data_;
Paul Stewartf0aae102011-10-19 12:11:44 -0700155 bool got_ready_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700156 scoped_ptr<Callback1<InputData*>::Type> data_callback_;
Paul Stewartf0aae102011-10-19 12:11:44 -0700157 scoped_ptr<Callback1<int>::Type> ready_callback_;
Paul Stewart26b327e2011-10-19 11:38:09 -0700158 scoped_ptr<IOHandler> input_handler_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700159 ScopedRunnableMethodFactory<MockEventDispatchTester> tester_factory_;
160 CancelableTask* failsafe_;
Paul Stewart75897df2011-04-27 09:05:53 -0700161};
162
163class ShillDaemonTest : public Test {
164 public:
165 ShillDaemonTest()
Darin Petkova7b89492011-07-27 12:48:17 -0700166 : daemon_(&config_, new MockControl()),
Darin Petkov887f2982011-07-14 16:10:17 -0700167 device_info_(daemon_.control_, dispatcher_, &daemon_.manager_),
168 dispatcher_(&daemon_.dispatcher_),
169 dispatcher_test_(dispatcher_),
170 factory_(this) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700171 }
172 virtual ~ShillDaemonTest() {}
Paul Stewart75897df2011-04-27 09:05:53 -0700173 virtual void SetUp() {
174 // Tests initialization done by the daemon's constructor
Chris Masone0e1d1042011-05-09 18:07:03 -0700175 ASSERT_NE(reinterpret_cast<Config*>(NULL), daemon_.config_);
176 ASSERT_NE(reinterpret_cast<ControlInterface*>(NULL), daemon_.control_);
Paul Stewartf0aae102011-10-19 12:11:44 -0700177 dispatcher_test_.ScheduleFailSafe();
Paul Stewart75897df2011-04-27 09:05:53 -0700178 }
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700179 protected:
Chris Masoneb9c00592011-10-06 13:10:39 -0700180 TestConfig config_;
Paul Stewart75897df2011-04-27 09:05:53 -0700181 Daemon daemon_;
Paul Stewart0af98bf2011-05-10 17:38:08 -0700182 DeviceInfo device_info_;
Paul Stewart75897df2011-04-27 09:05:53 -0700183 EventDispatcher *dispatcher_;
184 StrictMock<MockEventDispatchTester> dispatcher_test_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700185 ScopedRunnableMethodFactory<ShillDaemonTest> factory_;
Paul Stewart75897df2011-04-27 09:05:53 -0700186};
187
188
Paul Stewartf0aae102011-10-19 12:11:44 -0700189TEST_F(ShillDaemonTest, EventDispatcherTimer) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700190 EXPECT_CALL(dispatcher_test_, CallbackComplete(Gt(0)));
191 dispatcher_test_.ScheduleTimedTasks();
192 dispatcher_test_.RescheduleUnlessTriggered();
193 dispatcher_->DispatchForever();
Paul Stewartf0aae102011-10-19 12:11:44 -0700194}
Paul Stewarta43d9232011-05-10 11:40:22 -0700195
Paul Stewartf0aae102011-10-19 12:11:44 -0700196TEST_F(ShillDaemonTest, EventDispatcherIO) {
Paul Stewarta43d9232011-05-10 11:40:22 -0700197 EXPECT_CALL(dispatcher_test_, IOComplete(16));
198 int pipefd[2];
Chris Masone0e1d1042011-05-09 18:07:03 -0700199 ASSERT_EQ(pipe(pipefd), 0);
Paul Stewarta43d9232011-05-10 11:40:22 -0700200
201 dispatcher_test_.ListenIO(pipefd[0]);
Chris Masone0e1d1042011-05-09 18:07:03 -0700202 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
Paul Stewarta43d9232011-05-10 11:40:22 -0700203
Chris Masone0e1d1042011-05-09 18:07:03 -0700204 dispatcher_->DispatchForever();
Paul Stewarta43d9232011-05-10 11:40:22 -0700205 dispatcher_test_.StopListenIO();
Chris Masone0e1d1042011-05-09 18:07:03 -0700206}
207
Paul Stewartf0aae102011-10-19 12:11:44 -0700208TEST_F(ShillDaemonTest, EventDispatcherReady) {
209 EXPECT_CALL(dispatcher_test_, IOComplete(0))
210 .Times(1);
211 EXPECT_CALL(dispatcher_test_, IOComplete(1))
212 .Times(1);
213
214 int pipefd[2];
215 ASSERT_EQ(pipe(pipefd), 0);
216
217 dispatcher_test_.ListenReady(pipefd[0]);
218 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
219
220 dispatcher_->DispatchForever();
221 dispatcher_test_.StopListenReady();
222}
223
Chris Masone9be4a9d2011-05-16 15:44:09 -0700224} // namespace shill