blob: 564a9573054bd9c36b41379be9a26a4421858ab7 [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 "
79 << base::StringPrintf("%d %.*s", inputData->len,
80 inputData->len, inputData->buf);
Paul Stewarta43d9232011-05-10 11:40:22 -070081 got_data_ = true;
82 IOComplete(inputData->len);
Paul Stewartf0aae102011-10-19 12:11:44 -070083 StopDispatcher();
Paul Stewarta43d9232011-05-10 11:40:22 -070084 }
Chris Masone0e1d1042011-05-09 18:07:03 -070085
Paul Stewarta43d9232011-05-10 11:40:22 -070086 bool GetData() { return got_data_; }
87
88 void ListenIO(int fd) {
Paul Stewartf0aae102011-10-19 12:11:44 -070089 data_callback_.reset(
90 NewCallback(this, &MockEventDispatchTester::HandleData));
91 input_handler_.reset(
92 dispatcher_->CreateInputHandler(fd, data_callback_.get()));
Paul Stewarta43d9232011-05-10 11:40:22 -070093 }
94
95 void StopListenIO() {
96 got_data_ = false;
Chris Masone0e1d1042011-05-09 18:07:03 -070097 input_handler_.reset(NULL);
Paul Stewarta43d9232011-05-10 11:40:22 -070098 }
99
Paul Stewartf0aae102011-10-19 12:11:44 -0700100 void HandleReady(int fd) {
101 // Stop event handling after we receive in input-ready event. We should
102 // no longer be called until events are re-enabled.
103 input_handler_->Stop();
104
105 if (got_ready_) {
106 // If we're still getting events after we have stopped them, something
107 // is really wrong, and we cannot just depend on ASSERT_FALSE() to get
108 // us out of it. Make sure the dispatcher is also stopped, or else we
109 // could end up never exiting.
110 StopDispatcher();
111 ASSERT_FALSE(got_ready_) << "failed to stop Input Ready events";
112 }
113 got_ready_ = true;
114
115 LOG(INFO) << "MockEventDispatchTester handling ready for fd " << fd;
116 IOComplete(callback_count_);
117
118 if (callback_count_) {
119 StopDispatcher();
120 } else {
121 // Restart Ready events after 10 millisecond delay.
122 callback_count_++;
123 dispatcher_->PostDelayedTask(tester_factory_.NewRunnableMethod(
124 &MockEventDispatchTester::RestartReady), 10);
125 }
126 }
127
128 void RestartReady() {
129 got_ready_ = false;
130 input_handler_->Start();
131 }
132
133 void ListenReady(int fd) {
134 ready_callback_.reset(
135 NewCallback(this, &MockEventDispatchTester::HandleReady));
136 input_handler_.reset(
137 dispatcher_->CreateReadyHandler(fd, IOHandler::kModeInput,
138 ready_callback_.get()));
139 }
140
141 void StopListenReady() {
142 got_ready_ = false;
143 input_handler_.reset(NULL);
144 }
145
Paul Stewart75897df2011-04-27 09:05:53 -0700146 MOCK_METHOD1(CallbackComplete, void(int));
Paul Stewarta43d9232011-05-10 11:40:22 -0700147 MOCK_METHOD1(IOComplete, void(int));
Paul Stewart26b327e2011-10-19 11:38:09 -0700148
Paul Stewart75897df2011-04-27 09:05:53 -0700149 private:
Paul Stewarta43d9232011-05-10 11:40:22 -0700150 EventDispatcher *dispatcher_;
Paul Stewart75897df2011-04-27 09:05:53 -0700151 bool triggered_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700152 int callback_count_;
Paul Stewarta43d9232011-05-10 11:40:22 -0700153 bool got_data_;
Paul Stewartf0aae102011-10-19 12:11:44 -0700154 bool got_ready_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700155 scoped_ptr<Callback1<InputData*>::Type> data_callback_;
Paul Stewartf0aae102011-10-19 12:11:44 -0700156 scoped_ptr<Callback1<int>::Type> ready_callback_;
Paul Stewart26b327e2011-10-19 11:38:09 -0700157 scoped_ptr<IOHandler> input_handler_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700158 ScopedRunnableMethodFactory<MockEventDispatchTester> tester_factory_;
159 CancelableTask* failsafe_;
Paul Stewart75897df2011-04-27 09:05:53 -0700160};
161
162class ShillDaemonTest : public Test {
163 public:
164 ShillDaemonTest()
Darin Petkova7b89492011-07-27 12:48:17 -0700165 : daemon_(&config_, new MockControl()),
Darin Petkov887f2982011-07-14 16:10:17 -0700166 device_info_(daemon_.control_, dispatcher_, &daemon_.manager_),
167 dispatcher_(&daemon_.dispatcher_),
168 dispatcher_test_(dispatcher_),
169 factory_(this) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700170 }
171 virtual ~ShillDaemonTest() {}
Paul Stewart75897df2011-04-27 09:05:53 -0700172 virtual void SetUp() {
173 // Tests initialization done by the daemon's constructor
Chris Masone0e1d1042011-05-09 18:07:03 -0700174 ASSERT_NE(reinterpret_cast<Config*>(NULL), daemon_.config_);
175 ASSERT_NE(reinterpret_cast<ControlInterface*>(NULL), daemon_.control_);
Paul Stewartf0aae102011-10-19 12:11:44 -0700176 dispatcher_test_.ScheduleFailSafe();
Paul Stewart75897df2011-04-27 09:05:53 -0700177 }
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700178 protected:
Chris Masoneb9c00592011-10-06 13:10:39 -0700179 TestConfig config_;
Paul Stewart75897df2011-04-27 09:05:53 -0700180 Daemon daemon_;
Paul Stewart0af98bf2011-05-10 17:38:08 -0700181 DeviceInfo device_info_;
Paul Stewart75897df2011-04-27 09:05:53 -0700182 EventDispatcher *dispatcher_;
183 StrictMock<MockEventDispatchTester> dispatcher_test_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700184 ScopedRunnableMethodFactory<ShillDaemonTest> factory_;
Paul Stewart75897df2011-04-27 09:05:53 -0700185};
186
187
Paul Stewartf0aae102011-10-19 12:11:44 -0700188TEST_F(ShillDaemonTest, EventDispatcherTimer) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700189 EXPECT_CALL(dispatcher_test_, CallbackComplete(Gt(0)));
190 dispatcher_test_.ScheduleTimedTasks();
191 dispatcher_test_.RescheduleUnlessTriggered();
192 dispatcher_->DispatchForever();
Paul Stewartf0aae102011-10-19 12:11:44 -0700193}
Paul Stewarta43d9232011-05-10 11:40:22 -0700194
Paul Stewartf0aae102011-10-19 12:11:44 -0700195TEST_F(ShillDaemonTest, EventDispatcherIO) {
Paul Stewarta43d9232011-05-10 11:40:22 -0700196 EXPECT_CALL(dispatcher_test_, IOComplete(16));
197 int pipefd[2];
Chris Masone0e1d1042011-05-09 18:07:03 -0700198 ASSERT_EQ(pipe(pipefd), 0);
Paul Stewarta43d9232011-05-10 11:40:22 -0700199
200 dispatcher_test_.ListenIO(pipefd[0]);
Chris Masone0e1d1042011-05-09 18:07:03 -0700201 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
Paul Stewarta43d9232011-05-10 11:40:22 -0700202
Chris Masone0e1d1042011-05-09 18:07:03 -0700203 dispatcher_->DispatchForever();
Paul Stewarta43d9232011-05-10 11:40:22 -0700204 dispatcher_test_.StopListenIO();
Chris Masone0e1d1042011-05-09 18:07:03 -0700205}
206
Paul Stewartf0aae102011-10-19 12:11:44 -0700207TEST_F(ShillDaemonTest, EventDispatcherReady) {
208 EXPECT_CALL(dispatcher_test_, IOComplete(0))
209 .Times(1);
210 EXPECT_CALL(dispatcher_test_, IOComplete(1))
211 .Times(1);
212
213 int pipefd[2];
214 ASSERT_EQ(pipe(pipefd), 0);
215
216 dispatcher_test_.ListenReady(pipefd[0]);
217 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
218
219 dispatcher_->DispatchForever();
220 dispatcher_test_.StopListenReady();
221}
222
Chris Masone9be4a9d2011-05-16 15:44:09 -0700223} // namespace shill