blob: 8c78409949bf4a353da76d0666cd74c25bd7801f [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"
Thieu Le6c1e3bb2013-02-06 15:20:35 -080020#include "shill/mock_metrics.h"
Thieu Lefb46caf2012-03-08 11:57:15 -080021#include "shill/mock_proxy_factory.h"
22#include "shill/mock_rtnl_handler.h"
23#include "shill/mock_routing_table.h"
Paul Stewart75897df2011-04-27 09:05:53 -070024#include "shill/shill_daemon.h"
Chris Masoneb9c00592011-10-06 13:10:39 -070025#include "shill/shill_test_config.h"
Paul Stewart75897df2011-04-27 09:05:53 -070026
Eric Shienbrood3e20a232012-02-16 11:35:56 -050027using base::Bind;
28using base::Callback;
29using base::CancelableClosure;
Gary Moraina9fb3252012-05-31 12:05:31 -070030using base::Unretained;
Eric Shienbrood3e20a232012-02-16 11:35:56 -050031using base::WeakPtrFactory;
32
Thieu Lefb46caf2012-03-08 11:57:15 -080033using ::testing::Expectation;
Chris Masone0e1d1042011-05-09 18:07:03 -070034using ::testing::Gt;
Thieu Le6c1e3bb2013-02-06 15:20:35 -080035using ::testing::Mock;
Paul Stewart75897df2011-04-27 09:05:53 -070036using ::testing::NotNull;
37using ::testing::Return;
Paul Stewart75897df2011-04-27 09:05:53 -070038using ::testing::StrictMock;
Thieu Lefb46caf2012-03-08 11:57:15 -080039using ::testing::Test;
40using ::testing::_;
41
42namespace shill {
Paul Stewart75897df2011-04-27 09:05:53 -070043
44class MockEventDispatchTester {
45 public:
46 explicit MockEventDispatchTester(EventDispatcher *dispatcher)
Chris Masone0e1d1042011-05-09 18:07:03 -070047 : dispatcher_(dispatcher),
48 triggered_(false),
49 callback_count_(0),
50 got_data_(false),
Paul Stewartf0aae102011-10-19 12:11:44 -070051 got_ready_(false),
Chris Masone0e1d1042011-05-09 18:07:03 -070052 input_handler_(NULL),
53 tester_factory_(this) {
Paul Stewart75897df2011-04-27 09:05:53 -070054 }
55
Paul Stewartf0aae102011-10-19 12:11:44 -070056 void ScheduleFailSafe() {
57 // Set up a failsafe, so the test still exits even if something goes
Eric Shienbrood3e20a232012-02-16 11:35:56 -050058 // wrong.
59 failsafe_.Reset(Bind(&MockEventDispatchTester::StopDispatcher,
60 tester_factory_.GetWeakPtr()));
61 dispatcher_->PostDelayedTask(failsafe_.callback(), 100);
Paul Stewartf0aae102011-10-19 12:11:44 -070062 }
63
Chris Masone0e1d1042011-05-09 18:07:03 -070064 void ScheduleTimedTasks() {
65 dispatcher_->PostDelayedTask(
Eric Shienbrood3e20a232012-02-16 11:35:56 -050066 Bind(&MockEventDispatchTester::Trigger, tester_factory_.GetWeakPtr()),
Chris Masone0e1d1042011-05-09 18:07:03 -070067 10);
Paul Stewart75897df2011-04-27 09:05:53 -070068 }
69
Chris Masone0e1d1042011-05-09 18:07:03 -070070 void RescheduleUnlessTriggered() {
71 ++callback_count_;
Paul Stewart75897df2011-04-27 09:05:53 -070072 if (!triggered_) {
Chris Masone0e1d1042011-05-09 18:07:03 -070073 dispatcher_->PostTask(
Eric Shienbrood3e20a232012-02-16 11:35:56 -050074 Bind(&MockEventDispatchTester::RescheduleUnlessTriggered,
75 tester_factory_.GetWeakPtr()));
Chris Masone0e1d1042011-05-09 18:07:03 -070076 } else {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050077 failsafe_.Cancel();
Paul Stewartf0aae102011-10-19 12:11:44 -070078 StopDispatcher();
Paul Stewart75897df2011-04-27 09:05:53 -070079 }
80 }
81
Paul Stewartf0aae102011-10-19 12:11:44 -070082 void StopDispatcher() {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050083 dispatcher_->PostTask(MessageLoop::QuitClosure());
Chris Masone0e1d1042011-05-09 18:07:03 -070084 }
Paul Stewart75897df2011-04-27 09:05:53 -070085
Chris Masone0e1d1042011-05-09 18:07:03 -070086 void Trigger() {
87 LOG(INFO) << "MockEventDispatchTester handling " << callback_count_;
88 CallbackComplete(callback_count_);
89 triggered_ = true;
90 }
Paul Stewarta43d9232011-05-10 11:40:22 -070091
92 void HandleData(InputData *inputData) {
Chris Masone0e1d1042011-05-09 18:07:03 -070093 LOG(INFO) << "MockEventDispatchTester handling data len "
Paul Stewart83224402011-11-30 14:52:30 -080094 << base::StringPrintf("%zd %.*s", inputData->len,
95 static_cast<int>(inputData->len),
96 inputData->buf);
Paul Stewarta43d9232011-05-10 11:40:22 -070097 got_data_ = true;
98 IOComplete(inputData->len);
Paul Stewartf0aae102011-10-19 12:11:44 -070099 StopDispatcher();
Paul Stewarta43d9232011-05-10 11:40:22 -0700100 }
Chris Masone0e1d1042011-05-09 18:07:03 -0700101
Paul Stewarta43d9232011-05-10 11:40:22 -0700102 bool GetData() { return got_data_; }
103
104 void ListenIO(int fd) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500105 data_callback_ = Bind(&MockEventDispatchTester::HandleData,
106 tester_factory_.GetWeakPtr());
Paul Stewart5f06a0e2012-12-20 11:11:33 -0800107 input_handler_.reset(dispatcher_->CreateInputHandler(
108 fd, data_callback_, IOHandler::ErrorCallback()));
Paul Stewarta43d9232011-05-10 11:40:22 -0700109 }
110
111 void StopListenIO() {
112 got_data_ = false;
Chris Masone0e1d1042011-05-09 18:07:03 -0700113 input_handler_.reset(NULL);
Paul Stewarta43d9232011-05-10 11:40:22 -0700114 }
115
Paul Stewartf0aae102011-10-19 12:11:44 -0700116 void HandleReady(int fd) {
117 // Stop event handling after we receive in input-ready event. We should
118 // no longer be called until events are re-enabled.
119 input_handler_->Stop();
120
121 if (got_ready_) {
122 // If we're still getting events after we have stopped them, something
123 // is really wrong, and we cannot just depend on ASSERT_FALSE() to get
124 // us out of it. Make sure the dispatcher is also stopped, or else we
125 // could end up never exiting.
126 StopDispatcher();
127 ASSERT_FALSE(got_ready_) << "failed to stop Input Ready events";
128 }
129 got_ready_ = true;
130
131 LOG(INFO) << "MockEventDispatchTester handling ready for fd " << fd;
132 IOComplete(callback_count_);
133
134 if (callback_count_) {
135 StopDispatcher();
136 } else {
137 // Restart Ready events after 10 millisecond delay.
138 callback_count_++;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500139 dispatcher_->PostDelayedTask(
140 Bind(&MockEventDispatchTester::RestartReady,
141 tester_factory_.GetWeakPtr()),
142 10);
Paul Stewartf0aae102011-10-19 12:11:44 -0700143 }
144 }
145
146 void RestartReady() {
147 got_ready_ = false;
148 input_handler_->Start();
149 }
150
151 void ListenReady(int fd) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500152 ready_callback_ = Bind(&MockEventDispatchTester::HandleReady,
153 tester_factory_.GetWeakPtr());
Paul Stewartf0aae102011-10-19 12:11:44 -0700154 input_handler_.reset(
155 dispatcher_->CreateReadyHandler(fd, IOHandler::kModeInput,
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500156 ready_callback_));
Paul Stewartf0aae102011-10-19 12:11:44 -0700157 }
158
159 void StopListenReady() {
160 got_ready_ = false;
161 input_handler_.reset(NULL);
162 }
163
Paul Stewart75897df2011-04-27 09:05:53 -0700164 MOCK_METHOD1(CallbackComplete, void(int));
Paul Stewarta43d9232011-05-10 11:40:22 -0700165 MOCK_METHOD1(IOComplete, void(int));
Paul Stewart26b327e2011-10-19 11:38:09 -0700166
Paul Stewart75897df2011-04-27 09:05:53 -0700167 private:
Paul Stewarta43d9232011-05-10 11:40:22 -0700168 EventDispatcher *dispatcher_;
Paul Stewart75897df2011-04-27 09:05:53 -0700169 bool triggered_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700170 int callback_count_;
Paul Stewarta43d9232011-05-10 11:40:22 -0700171 bool got_data_;
Paul Stewartf0aae102011-10-19 12:11:44 -0700172 bool got_ready_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500173 Callback<void(InputData*)> data_callback_;
174 Callback<void(int)> ready_callback_;
Paul Stewart26b327e2011-10-19 11:38:09 -0700175 scoped_ptr<IOHandler> input_handler_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500176 WeakPtrFactory<MockEventDispatchTester> tester_factory_;
177 CancelableClosure failsafe_;
Paul Stewart75897df2011-04-27 09:05:53 -0700178};
179
180class ShillDaemonTest : public Test {
181 public:
182 ShillDaemonTest()
Darin Petkova7b89492011-07-27 12:48:17 -0700183 : daemon_(&config_, new MockControl()),
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800184 metrics_(new MockMetrics(&daemon_.dispatcher_)),
Thieu Lefb46caf2012-03-08 11:57:15 -0800185 manager_(new MockManager(daemon_.control_,
186 &daemon_.dispatcher_,
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800187 metrics_,
Thieu Lefb46caf2012-03-08 11:57:15 -0800188 &daemon_.glib_)),
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800189 device_info_(daemon_.control_, dispatcher_, metrics_,
Thieu Lefb46caf2012-03-08 11:57:15 -0800190 daemon_.manager_.get()),
Darin Petkov887f2982011-07-14 16:10:17 -0700191 dispatcher_(&daemon_.dispatcher_),
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500192 dispatcher_test_(dispatcher_) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700193 }
194 virtual ~ShillDaemonTest() {}
Paul Stewart75897df2011-04-27 09:05:53 -0700195 virtual void SetUp() {
196 // Tests initialization done by the daemon's constructor
Chris Masone0e1d1042011-05-09 18:07:03 -0700197 ASSERT_NE(reinterpret_cast<Config*>(NULL), daemon_.config_);
198 ASSERT_NE(reinterpret_cast<ControlInterface*>(NULL), daemon_.control_);
Thieu Lefb46caf2012-03-08 11:57:15 -0800199 daemon_.proxy_factory_ = &proxy_factory_;
200 daemon_.rtnl_handler_ = &rtnl_handler_;
201 daemon_.routing_table_ = &routing_table_;
202 daemon_.dhcp_provider_ = &dhcp_provider_;
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800203 daemon_.metrics_.reset(metrics_); // Passes ownership
Thieu Lefb46caf2012-03-08 11:57:15 -0800204 daemon_.manager_.reset(manager_); // Passes ownership
Paul Stewartf0aae102011-10-19 12:11:44 -0700205 dispatcher_test_.ScheduleFailSafe();
Paul Stewart75897df2011-04-27 09:05:53 -0700206 }
Thieu Lefb46caf2012-03-08 11:57:15 -0800207 void StartDaemon() {
208 daemon_.Start();
209 }
210
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800211 void StopDaemon() {
212 daemon_.Stop();
213 }
214
Wade Guthriebb9fca22013-04-10 17:21:42 -0700215 void ResetNetlinkManager() {
216 daemon_.netlink_manager_->Reset(true);
Darin Petkovd5818382013-01-28 16:27:07 +0100217 }
218
Gary Moraina9fb3252012-05-31 12:05:31 -0700219 MOCK_METHOD0(TerminationAction, void());
220
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700221 protected:
Chris Masoneb9c00592011-10-06 13:10:39 -0700222 TestConfig config_;
Paul Stewart75897df2011-04-27 09:05:53 -0700223 Daemon daemon_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800224 MockProxyFactory proxy_factory_;
225 MockRTNLHandler rtnl_handler_;
226 MockRoutingTable routing_table_;
227 MockDHCPProvider dhcp_provider_;
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800228 MockMetrics *metrics_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800229 MockManager *manager_;
Paul Stewart0af98bf2011-05-10 17:38:08 -0700230 DeviceInfo device_info_;
Paul Stewart75897df2011-04-27 09:05:53 -0700231 EventDispatcher *dispatcher_;
232 StrictMock<MockEventDispatchTester> dispatcher_test_;
233};
234
235
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800236TEST_F(ShillDaemonTest, StartStop) {
Thieu Lefb46caf2012-03-08 11:57:15 -0800237 // To ensure we do not have any stale routes, we flush a device's routes
238 // when it is started. This requires that the routing table is fully
239 // populated before we create and start devices. So test to make sure that
240 // the RoutingTable starts before the Manager (which in turn starts
241 // DeviceInfo who is responsible for creating and starting devices).
242 // The result is that we request the dump of the routing table and when that
243 // completes, we request the dump of the links. For each link found, we
244 // create and start the device.
245 EXPECT_CALL(proxy_factory_, Init());
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800246 EXPECT_CALL(*metrics_, Start());
Thieu Lefb46caf2012-03-08 11:57:15 -0800247 EXPECT_CALL(rtnl_handler_, Start(_, _));
248 Expectation routing_table_started = EXPECT_CALL(routing_table_, Start());
249 EXPECT_CALL(dhcp_provider_, Init(_, _, _));
250 EXPECT_CALL(*manager_, Start()).After(routing_table_started);
251 StartDaemon();
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800252 Mock::VerifyAndClearExpectations(metrics_);
253 Mock::VerifyAndClearExpectations(manager_);
254
255 EXPECT_CALL(*manager_, Stop());
256 EXPECT_CALL(*metrics_, Stop());
257 StopDaemon();
Thieu Lefb46caf2012-03-08 11:57:15 -0800258}
259
Paul Stewartf0aae102011-10-19 12:11:44 -0700260TEST_F(ShillDaemonTest, EventDispatcherTimer) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700261 EXPECT_CALL(dispatcher_test_, CallbackComplete(Gt(0)));
262 dispatcher_test_.ScheduleTimedTasks();
263 dispatcher_test_.RescheduleUnlessTriggered();
264 dispatcher_->DispatchForever();
Paul Stewartf0aae102011-10-19 12:11:44 -0700265}
Paul Stewarta43d9232011-05-10 11:40:22 -0700266
Paul Stewartf0aae102011-10-19 12:11:44 -0700267TEST_F(ShillDaemonTest, EventDispatcherIO) {
Paul Stewarta43d9232011-05-10 11:40:22 -0700268 EXPECT_CALL(dispatcher_test_, IOComplete(16));
269 int pipefd[2];
Chris Masone0e1d1042011-05-09 18:07:03 -0700270 ASSERT_EQ(pipe(pipefd), 0);
Paul Stewarta43d9232011-05-10 11:40:22 -0700271
272 dispatcher_test_.ListenIO(pipefd[0]);
Chris Masone0e1d1042011-05-09 18:07:03 -0700273 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
Paul Stewarta43d9232011-05-10 11:40:22 -0700274
Chris Masone0e1d1042011-05-09 18:07:03 -0700275 dispatcher_->DispatchForever();
Paul Stewarta43d9232011-05-10 11:40:22 -0700276 dispatcher_test_.StopListenIO();
Chris Masone0e1d1042011-05-09 18:07:03 -0700277}
278
Paul Stewartf0aae102011-10-19 12:11:44 -0700279TEST_F(ShillDaemonTest, EventDispatcherReady) {
280 EXPECT_CALL(dispatcher_test_, IOComplete(0))
281 .Times(1);
282 EXPECT_CALL(dispatcher_test_, IOComplete(1))
283 .Times(1);
284
285 int pipefd[2];
286 ASSERT_EQ(pipe(pipefd), 0);
287
288 dispatcher_test_.ListenReady(pipefd[0]);
289 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
290
291 dispatcher_->DispatchForever();
292 dispatcher_test_.StopListenReady();
293}
294
Gary Moraina9fb3252012-05-31 12:05:31 -0700295ACTION_P2(CompleteAction, manager, name) {
296 manager->TerminationActionComplete(name);
297}
298
299TEST_F(ShillDaemonTest, Quit) {
300 // The following expectations are to satisfy calls in Daemon::Start().
301 EXPECT_CALL(proxy_factory_, Init());
302 EXPECT_CALL(rtnl_handler_, Start(_, _));
303 EXPECT_CALL(routing_table_, Start());
304 EXPECT_CALL(dhcp_provider_, Init(_, _, _));
305 EXPECT_CALL(*manager_, Start());
306
307 // This expectation verifies that the termination actions are invoked.
308 EXPECT_CALL(*this, TerminationAction())
309 .WillOnce(CompleteAction(manager_, "daemon test"));
310
311 manager_->AddTerminationAction("daemon test",
312 Bind(&ShillDaemonTest::TerminationAction,
313 Unretained(this)));
314
315 // Run Daemon::Quit() after the daemon starts running.
316 dispatcher_->PostTask(Bind(&Daemon::Quit, Unretained(&daemon_)));
Wade Guthriebee87c22013-03-06 11:00:46 -0800317
318 // TODO(wdg): crbug.com/224712 - Need fix for "GLib-WARNING **: Invalid file
Wade Guthriebb9fca22013-04-10 17:21:42 -0700319 // descriptor". This requires support for netlink_manager interface tests.
Gary Moraina9fb3252012-05-31 12:05:31 -0700320 daemon_.Run();
Wade Guthriebb9fca22013-04-10 17:21:42 -0700321 ResetNetlinkManager();
Gary Moraina9fb3252012-05-31 12:05:31 -0700322}
323
Chris Masone9be4a9d2011-05-16 15:44:09 -0700324} // namespace shill