blob: 0602aaa2a47fc5a82368171c9da53d89185acec7 [file] [log] [blame]
Thieu Le3426c8f2012-01-11 17:35:11 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewart75897df2011-04-27 09:05:53 -07002// 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
Eric Shienbrood3e20a232012-02-16 11:35:56 -05007#include <base/bind.h>
8#include <base/cancelable_callback.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"
Christopher Wileyb691efd2012-08-09 13:51:51 -070016#include "shill/logging.h"
Darin Petkov887f2982011-07-14 16:10:17 -070017#include "shill/mock_control.h"
Thieu Lefb46caf2012-03-08 11:57:15 -080018#include "shill/mock_dhcp_provider.h"
19#include "shill/mock_manager.h"
20#include "shill/mock_proxy_factory.h"
21#include "shill/mock_rtnl_handler.h"
22#include "shill/mock_routing_table.h"
Paul Stewart75897df2011-04-27 09:05:53 -070023#include "shill/shill_daemon.h"
Chris Masoneb9c00592011-10-06 13:10:39 -070024#include "shill/shill_test_config.h"
Paul Stewart75897df2011-04-27 09:05:53 -070025
Eric Shienbrood3e20a232012-02-16 11:35:56 -050026using base::Bind;
27using base::Callback;
28using base::CancelableClosure;
Gary Moraina9fb3252012-05-31 12:05:31 -070029using base::Unretained;
Eric Shienbrood3e20a232012-02-16 11:35:56 -050030using base::WeakPtrFactory;
31
Thieu Lefb46caf2012-03-08 11:57:15 -080032using ::testing::Expectation;
Chris Masone0e1d1042011-05-09 18:07:03 -070033using ::testing::Gt;
Paul Stewart75897df2011-04-27 09:05:53 -070034using ::testing::NotNull;
35using ::testing::Return;
Paul Stewart75897df2011-04-27 09:05:53 -070036using ::testing::StrictMock;
Thieu Lefb46caf2012-03-08 11:57:15 -080037using ::testing::Test;
38using ::testing::_;
39
40namespace shill {
Paul Stewart75897df2011-04-27 09:05:53 -070041
42class MockEventDispatchTester {
43 public:
44 explicit MockEventDispatchTester(EventDispatcher *dispatcher)
Chris Masone0e1d1042011-05-09 18:07:03 -070045 : dispatcher_(dispatcher),
46 triggered_(false),
47 callback_count_(0),
48 got_data_(false),
Paul Stewartf0aae102011-10-19 12:11:44 -070049 got_ready_(false),
Chris Masone0e1d1042011-05-09 18:07:03 -070050 input_handler_(NULL),
51 tester_factory_(this) {
Paul Stewart75897df2011-04-27 09:05:53 -070052 }
53
Paul Stewartf0aae102011-10-19 12:11:44 -070054 void ScheduleFailSafe() {
55 // Set up a failsafe, so the test still exits even if something goes
Eric Shienbrood3e20a232012-02-16 11:35:56 -050056 // wrong.
57 failsafe_.Reset(Bind(&MockEventDispatchTester::StopDispatcher,
58 tester_factory_.GetWeakPtr()));
59 dispatcher_->PostDelayedTask(failsafe_.callback(), 100);
Paul Stewartf0aae102011-10-19 12:11:44 -070060 }
61
Chris Masone0e1d1042011-05-09 18:07:03 -070062 void ScheduleTimedTasks() {
63 dispatcher_->PostDelayedTask(
Eric Shienbrood3e20a232012-02-16 11:35:56 -050064 Bind(&MockEventDispatchTester::Trigger, tester_factory_.GetWeakPtr()),
Chris Masone0e1d1042011-05-09 18:07:03 -070065 10);
Paul Stewart75897df2011-04-27 09:05:53 -070066 }
67
Chris Masone0e1d1042011-05-09 18:07:03 -070068 void RescheduleUnlessTriggered() {
69 ++callback_count_;
Paul Stewart75897df2011-04-27 09:05:53 -070070 if (!triggered_) {
Chris Masone0e1d1042011-05-09 18:07:03 -070071 dispatcher_->PostTask(
Eric Shienbrood3e20a232012-02-16 11:35:56 -050072 Bind(&MockEventDispatchTester::RescheduleUnlessTriggered,
73 tester_factory_.GetWeakPtr()));
Chris Masone0e1d1042011-05-09 18:07:03 -070074 } else {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050075 failsafe_.Cancel();
Paul Stewartf0aae102011-10-19 12:11:44 -070076 StopDispatcher();
Paul Stewart75897df2011-04-27 09:05:53 -070077 }
78 }
79
Paul Stewartf0aae102011-10-19 12:11:44 -070080 void StopDispatcher() {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050081 dispatcher_->PostTask(MessageLoop::QuitClosure());
Chris Masone0e1d1042011-05-09 18:07:03 -070082 }
Paul Stewart75897df2011-04-27 09:05:53 -070083
Chris Masone0e1d1042011-05-09 18:07:03 -070084 void Trigger() {
85 LOG(INFO) << "MockEventDispatchTester handling " << callback_count_;
86 CallbackComplete(callback_count_);
87 triggered_ = true;
88 }
Paul Stewarta43d9232011-05-10 11:40:22 -070089
90 void HandleData(InputData *inputData) {
Chris Masone0e1d1042011-05-09 18:07:03 -070091 LOG(INFO) << "MockEventDispatchTester handling data len "
Paul Stewart83224402011-11-30 14:52:30 -080092 << base::StringPrintf("%zd %.*s", inputData->len,
93 static_cast<int>(inputData->len),
94 inputData->buf);
Paul Stewarta43d9232011-05-10 11:40:22 -070095 got_data_ = true;
96 IOComplete(inputData->len);
Paul Stewartf0aae102011-10-19 12:11:44 -070097 StopDispatcher();
Paul Stewarta43d9232011-05-10 11:40:22 -070098 }
Chris Masone0e1d1042011-05-09 18:07:03 -070099
Paul Stewarta43d9232011-05-10 11:40:22 -0700100 bool GetData() { return got_data_; }
101
102 void ListenIO(int fd) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500103 data_callback_ = Bind(&MockEventDispatchTester::HandleData,
104 tester_factory_.GetWeakPtr());
Paul Stewartf0aae102011-10-19 12:11:44 -0700105 input_handler_.reset(
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500106 dispatcher_->CreateInputHandler(fd, data_callback_));
Paul Stewarta43d9232011-05-10 11:40:22 -0700107 }
108
109 void StopListenIO() {
110 got_data_ = false;
Chris Masone0e1d1042011-05-09 18:07:03 -0700111 input_handler_.reset(NULL);
Paul Stewarta43d9232011-05-10 11:40:22 -0700112 }
113
Paul Stewartf0aae102011-10-19 12:11:44 -0700114 void HandleReady(int fd) {
115 // Stop event handling after we receive in input-ready event. We should
116 // no longer be called until events are re-enabled.
117 input_handler_->Stop();
118
119 if (got_ready_) {
120 // If we're still getting events after we have stopped them, something
121 // is really wrong, and we cannot just depend on ASSERT_FALSE() to get
122 // us out of it. Make sure the dispatcher is also stopped, or else we
123 // could end up never exiting.
124 StopDispatcher();
125 ASSERT_FALSE(got_ready_) << "failed to stop Input Ready events";
126 }
127 got_ready_ = true;
128
129 LOG(INFO) << "MockEventDispatchTester handling ready for fd " << fd;
130 IOComplete(callback_count_);
131
132 if (callback_count_) {
133 StopDispatcher();
134 } else {
135 // Restart Ready events after 10 millisecond delay.
136 callback_count_++;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500137 dispatcher_->PostDelayedTask(
138 Bind(&MockEventDispatchTester::RestartReady,
139 tester_factory_.GetWeakPtr()),
140 10);
Paul Stewartf0aae102011-10-19 12:11:44 -0700141 }
142 }
143
144 void RestartReady() {
145 got_ready_ = false;
146 input_handler_->Start();
147 }
148
149 void ListenReady(int fd) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500150 ready_callback_ = Bind(&MockEventDispatchTester::HandleReady,
151 tester_factory_.GetWeakPtr());
Paul Stewartf0aae102011-10-19 12:11:44 -0700152 input_handler_.reset(
153 dispatcher_->CreateReadyHandler(fd, IOHandler::kModeInput,
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500154 ready_callback_));
Paul Stewartf0aae102011-10-19 12:11:44 -0700155 }
156
157 void StopListenReady() {
158 got_ready_ = false;
159 input_handler_.reset(NULL);
160 }
161
Paul Stewart75897df2011-04-27 09:05:53 -0700162 MOCK_METHOD1(CallbackComplete, void(int));
Paul Stewarta43d9232011-05-10 11:40:22 -0700163 MOCK_METHOD1(IOComplete, void(int));
Paul Stewart26b327e2011-10-19 11:38:09 -0700164
Paul Stewart75897df2011-04-27 09:05:53 -0700165 private:
Paul Stewarta43d9232011-05-10 11:40:22 -0700166 EventDispatcher *dispatcher_;
Paul Stewart75897df2011-04-27 09:05:53 -0700167 bool triggered_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700168 int callback_count_;
Paul Stewarta43d9232011-05-10 11:40:22 -0700169 bool got_data_;
Paul Stewartf0aae102011-10-19 12:11:44 -0700170 bool got_ready_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500171 Callback<void(InputData*)> data_callback_;
172 Callback<void(int)> ready_callback_;
Paul Stewart26b327e2011-10-19 11:38:09 -0700173 scoped_ptr<IOHandler> input_handler_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500174 WeakPtrFactory<MockEventDispatchTester> tester_factory_;
175 CancelableClosure failsafe_;
Paul Stewart75897df2011-04-27 09:05:53 -0700176};
177
178class ShillDaemonTest : public Test {
179 public:
180 ShillDaemonTest()
Darin Petkova7b89492011-07-27 12:48:17 -0700181 : daemon_(&config_, new MockControl()),
Thieu Lefb46caf2012-03-08 11:57:15 -0800182 manager_(new MockManager(daemon_.control_,
183 &daemon_.dispatcher_,
184 &daemon_.metrics_,
185 &daemon_.glib_)),
Thieu Le3426c8f2012-01-11 17:35:11 -0800186 device_info_(daemon_.control_, dispatcher_, &daemon_.metrics_,
Thieu Lefb46caf2012-03-08 11:57:15 -0800187 daemon_.manager_.get()),
Darin Petkov887f2982011-07-14 16:10:17 -0700188 dispatcher_(&daemon_.dispatcher_),
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500189 dispatcher_test_(dispatcher_) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700190 }
191 virtual ~ShillDaemonTest() {}
Paul Stewart75897df2011-04-27 09:05:53 -0700192 virtual void SetUp() {
193 // Tests initialization done by the daemon's constructor
Chris Masone0e1d1042011-05-09 18:07:03 -0700194 ASSERT_NE(reinterpret_cast<Config*>(NULL), daemon_.config_);
195 ASSERT_NE(reinterpret_cast<ControlInterface*>(NULL), daemon_.control_);
Thieu Lefb46caf2012-03-08 11:57:15 -0800196 daemon_.proxy_factory_ = &proxy_factory_;
197 daemon_.rtnl_handler_ = &rtnl_handler_;
198 daemon_.routing_table_ = &routing_table_;
199 daemon_.dhcp_provider_ = &dhcp_provider_;
200 daemon_.manager_.reset(manager_); // Passes ownership
Paul Stewartf0aae102011-10-19 12:11:44 -0700201 dispatcher_test_.ScheduleFailSafe();
Paul Stewart75897df2011-04-27 09:05:53 -0700202 }
Thieu Lefb46caf2012-03-08 11:57:15 -0800203 void StartDaemon() {
204 daemon_.Start();
205 }
206
Gary Moraina9fb3252012-05-31 12:05:31 -0700207 MOCK_METHOD0(TerminationAction, void());
208
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700209 protected:
Chris Masoneb9c00592011-10-06 13:10:39 -0700210 TestConfig config_;
Paul Stewart75897df2011-04-27 09:05:53 -0700211 Daemon daemon_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800212 MockProxyFactory proxy_factory_;
213 MockRTNLHandler rtnl_handler_;
214 MockRoutingTable routing_table_;
215 MockDHCPProvider dhcp_provider_;
216 MockManager *manager_;
Paul Stewart0af98bf2011-05-10 17:38:08 -0700217 DeviceInfo device_info_;
Paul Stewart75897df2011-04-27 09:05:53 -0700218 EventDispatcher *dispatcher_;
219 StrictMock<MockEventDispatchTester> dispatcher_test_;
220};
221
222
Thieu Lefb46caf2012-03-08 11:57:15 -0800223TEST_F(ShillDaemonTest, Start) {
224 // To ensure we do not have any stale routes, we flush a device's routes
225 // when it is started. This requires that the routing table is fully
226 // populated before we create and start devices. So test to make sure that
227 // the RoutingTable starts before the Manager (which in turn starts
228 // DeviceInfo who is responsible for creating and starting devices).
229 // The result is that we request the dump of the routing table and when that
230 // completes, we request the dump of the links. For each link found, we
231 // create and start the device.
232 EXPECT_CALL(proxy_factory_, Init());
233 EXPECT_CALL(rtnl_handler_, Start(_, _));
234 Expectation routing_table_started = EXPECT_CALL(routing_table_, Start());
235 EXPECT_CALL(dhcp_provider_, Init(_, _, _));
236 EXPECT_CALL(*manager_, Start()).After(routing_table_started);
237 StartDaemon();
238}
239
Paul Stewartf0aae102011-10-19 12:11:44 -0700240TEST_F(ShillDaemonTest, EventDispatcherTimer) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700241 EXPECT_CALL(dispatcher_test_, CallbackComplete(Gt(0)));
242 dispatcher_test_.ScheduleTimedTasks();
243 dispatcher_test_.RescheduleUnlessTriggered();
244 dispatcher_->DispatchForever();
Paul Stewartf0aae102011-10-19 12:11:44 -0700245}
Paul Stewarta43d9232011-05-10 11:40:22 -0700246
Paul Stewartf0aae102011-10-19 12:11:44 -0700247TEST_F(ShillDaemonTest, EventDispatcherIO) {
Paul Stewarta43d9232011-05-10 11:40:22 -0700248 EXPECT_CALL(dispatcher_test_, IOComplete(16));
249 int pipefd[2];
Chris Masone0e1d1042011-05-09 18:07:03 -0700250 ASSERT_EQ(pipe(pipefd), 0);
Paul Stewarta43d9232011-05-10 11:40:22 -0700251
252 dispatcher_test_.ListenIO(pipefd[0]);
Chris Masone0e1d1042011-05-09 18:07:03 -0700253 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
Paul Stewarta43d9232011-05-10 11:40:22 -0700254
Chris Masone0e1d1042011-05-09 18:07:03 -0700255 dispatcher_->DispatchForever();
Paul Stewarta43d9232011-05-10 11:40:22 -0700256 dispatcher_test_.StopListenIO();
Chris Masone0e1d1042011-05-09 18:07:03 -0700257}
258
Paul Stewartf0aae102011-10-19 12:11:44 -0700259TEST_F(ShillDaemonTest, EventDispatcherReady) {
260 EXPECT_CALL(dispatcher_test_, IOComplete(0))
261 .Times(1);
262 EXPECT_CALL(dispatcher_test_, IOComplete(1))
263 .Times(1);
264
265 int pipefd[2];
266 ASSERT_EQ(pipe(pipefd), 0);
267
268 dispatcher_test_.ListenReady(pipefd[0]);
269 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
270
271 dispatcher_->DispatchForever();
272 dispatcher_test_.StopListenReady();
273}
274
Gary Moraina9fb3252012-05-31 12:05:31 -0700275ACTION_P2(CompleteAction, manager, name) {
276 manager->TerminationActionComplete(name);
277}
278
279TEST_F(ShillDaemonTest, Quit) {
280 // The following expectations are to satisfy calls in Daemon::Start().
281 EXPECT_CALL(proxy_factory_, Init());
282 EXPECT_CALL(rtnl_handler_, Start(_, _));
283 EXPECT_CALL(routing_table_, Start());
284 EXPECT_CALL(dhcp_provider_, Init(_, _, _));
285 EXPECT_CALL(*manager_, Start());
286
287 // This expectation verifies that the termination actions are invoked.
288 EXPECT_CALL(*this, TerminationAction())
289 .WillOnce(CompleteAction(manager_, "daemon test"));
290
291 manager_->AddTerminationAction("daemon test",
292 Bind(&ShillDaemonTest::TerminationAction,
293 Unretained(this)));
294
295 // Run Daemon::Quit() after the daemon starts running.
296 dispatcher_->PostTask(Bind(&Daemon::Quit, Unretained(&daemon_)));
297 daemon_.Run();
298}
299
300
Chris Masone9be4a9d2011-05-16 15:44:09 -0700301} // namespace shill