blob: 19eb37d639c057c1e4b2eab9cfa5c3c575bfb2cf [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"
Wade Guthriefa2100e2013-05-15 10:11:22 -070021#include "shill/mock_netlink_manager.h"
Thieu Lefb46caf2012-03-08 11:57:15 -080022#include "shill/mock_proxy_factory.h"
Thieu Lefb46caf2012-03-08 11:57:15 -080023#include "shill/mock_routing_table.h"
Wade Guthriefa2100e2013-05-15 10:11:22 -070024#include "shill/mock_rtnl_handler.h"
25#include "shill/nl80211_message.h"
Paul Stewart75897df2011-04-27 09:05:53 -070026#include "shill/shill_daemon.h"
Chris Masoneb9c00592011-10-06 13:10:39 -070027#include "shill/shill_test_config.h"
Paul Stewart75897df2011-04-27 09:05:53 -070028
Eric Shienbrood3e20a232012-02-16 11:35:56 -050029using base::Bind;
30using base::Callback;
31using base::CancelableClosure;
Gary Moraina9fb3252012-05-31 12:05:31 -070032using base::Unretained;
Eric Shienbrood3e20a232012-02-16 11:35:56 -050033using base::WeakPtrFactory;
34
Thieu Lefb46caf2012-03-08 11:57:15 -080035using ::testing::Expectation;
Chris Masone0e1d1042011-05-09 18:07:03 -070036using ::testing::Gt;
Thieu Le6c1e3bb2013-02-06 15:20:35 -080037using ::testing::Mock;
Paul Stewart75897df2011-04-27 09:05:53 -070038using ::testing::NotNull;
39using ::testing::Return;
Paul Stewart75897df2011-04-27 09:05:53 -070040using ::testing::StrictMock;
Thieu Lefb46caf2012-03-08 11:57:15 -080041using ::testing::Test;
42using ::testing::_;
43
44namespace shill {
Paul Stewart75897df2011-04-27 09:05:53 -070045
46class MockEventDispatchTester {
47 public:
48 explicit MockEventDispatchTester(EventDispatcher *dispatcher)
Chris Masone0e1d1042011-05-09 18:07:03 -070049 : dispatcher_(dispatcher),
50 triggered_(false),
51 callback_count_(0),
52 got_data_(false),
Paul Stewartf0aae102011-10-19 12:11:44 -070053 got_ready_(false),
Chris Masone0e1d1042011-05-09 18:07:03 -070054 input_handler_(NULL),
55 tester_factory_(this) {
Paul Stewart75897df2011-04-27 09:05:53 -070056 }
57
Paul Stewartf0aae102011-10-19 12:11:44 -070058 void ScheduleFailSafe() {
59 // Set up a failsafe, so the test still exits even if something goes
Eric Shienbrood3e20a232012-02-16 11:35:56 -050060 // wrong.
61 failsafe_.Reset(Bind(&MockEventDispatchTester::StopDispatcher,
62 tester_factory_.GetWeakPtr()));
63 dispatcher_->PostDelayedTask(failsafe_.callback(), 100);
Paul Stewartf0aae102011-10-19 12:11:44 -070064 }
65
Chris Masone0e1d1042011-05-09 18:07:03 -070066 void ScheduleTimedTasks() {
67 dispatcher_->PostDelayedTask(
Eric Shienbrood3e20a232012-02-16 11:35:56 -050068 Bind(&MockEventDispatchTester::Trigger, tester_factory_.GetWeakPtr()),
Chris Masone0e1d1042011-05-09 18:07:03 -070069 10);
Paul Stewart75897df2011-04-27 09:05:53 -070070 }
71
Chris Masone0e1d1042011-05-09 18:07:03 -070072 void RescheduleUnlessTriggered() {
73 ++callback_count_;
Paul Stewart75897df2011-04-27 09:05:53 -070074 if (!triggered_) {
Chris Masone0e1d1042011-05-09 18:07:03 -070075 dispatcher_->PostTask(
Eric Shienbrood3e20a232012-02-16 11:35:56 -050076 Bind(&MockEventDispatchTester::RescheduleUnlessTriggered,
77 tester_factory_.GetWeakPtr()));
Chris Masone0e1d1042011-05-09 18:07:03 -070078 } else {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050079 failsafe_.Cancel();
Paul Stewartf0aae102011-10-19 12:11:44 -070080 StopDispatcher();
Paul Stewart75897df2011-04-27 09:05:53 -070081 }
82 }
83
Paul Stewartf0aae102011-10-19 12:11:44 -070084 void StopDispatcher() {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050085 dispatcher_->PostTask(MessageLoop::QuitClosure());
Chris Masone0e1d1042011-05-09 18:07:03 -070086 }
Paul Stewart75897df2011-04-27 09:05:53 -070087
Chris Masone0e1d1042011-05-09 18:07:03 -070088 void Trigger() {
89 LOG(INFO) << "MockEventDispatchTester handling " << callback_count_;
90 CallbackComplete(callback_count_);
91 triggered_ = true;
92 }
Paul Stewarta43d9232011-05-10 11:40:22 -070093
94 void HandleData(InputData *inputData) {
Chris Masone0e1d1042011-05-09 18:07:03 -070095 LOG(INFO) << "MockEventDispatchTester handling data len "
Paul Stewart83224402011-11-30 14:52:30 -080096 << base::StringPrintf("%zd %.*s", inputData->len,
97 static_cast<int>(inputData->len),
98 inputData->buf);
Paul Stewarta43d9232011-05-10 11:40:22 -070099 got_data_ = true;
100 IOComplete(inputData->len);
Paul Stewartf0aae102011-10-19 12:11:44 -0700101 StopDispatcher();
Paul Stewarta43d9232011-05-10 11:40:22 -0700102 }
Chris Masone0e1d1042011-05-09 18:07:03 -0700103
Paul Stewarta43d9232011-05-10 11:40:22 -0700104 bool GetData() { return got_data_; }
105
106 void ListenIO(int fd) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500107 data_callback_ = Bind(&MockEventDispatchTester::HandleData,
108 tester_factory_.GetWeakPtr());
Paul Stewart5f06a0e2012-12-20 11:11:33 -0800109 input_handler_.reset(dispatcher_->CreateInputHandler(
110 fd, data_callback_, IOHandler::ErrorCallback()));
Paul Stewarta43d9232011-05-10 11:40:22 -0700111 }
112
113 void StopListenIO() {
114 got_data_ = false;
Chris Masone0e1d1042011-05-09 18:07:03 -0700115 input_handler_.reset(NULL);
Paul Stewarta43d9232011-05-10 11:40:22 -0700116 }
117
Paul Stewartf0aae102011-10-19 12:11:44 -0700118 void HandleReady(int fd) {
119 // Stop event handling after we receive in input-ready event. We should
120 // no longer be called until events are re-enabled.
121 input_handler_->Stop();
122
123 if (got_ready_) {
124 // If we're still getting events after we have stopped them, something
125 // is really wrong, and we cannot just depend on ASSERT_FALSE() to get
126 // us out of it. Make sure the dispatcher is also stopped, or else we
127 // could end up never exiting.
128 StopDispatcher();
129 ASSERT_FALSE(got_ready_) << "failed to stop Input Ready events";
130 }
131 got_ready_ = true;
132
133 LOG(INFO) << "MockEventDispatchTester handling ready for fd " << fd;
134 IOComplete(callback_count_);
135
136 if (callback_count_) {
137 StopDispatcher();
138 } else {
139 // Restart Ready events after 10 millisecond delay.
140 callback_count_++;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500141 dispatcher_->PostDelayedTask(
142 Bind(&MockEventDispatchTester::RestartReady,
143 tester_factory_.GetWeakPtr()),
144 10);
Paul Stewartf0aae102011-10-19 12:11:44 -0700145 }
146 }
147
148 void RestartReady() {
149 got_ready_ = false;
150 input_handler_->Start();
151 }
152
153 void ListenReady(int fd) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500154 ready_callback_ = Bind(&MockEventDispatchTester::HandleReady,
155 tester_factory_.GetWeakPtr());
Paul Stewartf0aae102011-10-19 12:11:44 -0700156 input_handler_.reset(
157 dispatcher_->CreateReadyHandler(fd, IOHandler::kModeInput,
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500158 ready_callback_));
Paul Stewartf0aae102011-10-19 12:11:44 -0700159 }
160
161 void StopListenReady() {
162 got_ready_ = false;
163 input_handler_.reset(NULL);
164 }
165
Paul Stewart75897df2011-04-27 09:05:53 -0700166 MOCK_METHOD1(CallbackComplete, void(int));
Paul Stewarta43d9232011-05-10 11:40:22 -0700167 MOCK_METHOD1(IOComplete, void(int));
Paul Stewart26b327e2011-10-19 11:38:09 -0700168
Paul Stewart75897df2011-04-27 09:05:53 -0700169 private:
Paul Stewarta43d9232011-05-10 11:40:22 -0700170 EventDispatcher *dispatcher_;
Paul Stewart75897df2011-04-27 09:05:53 -0700171 bool triggered_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700172 int callback_count_;
Paul Stewarta43d9232011-05-10 11:40:22 -0700173 bool got_data_;
Paul Stewartf0aae102011-10-19 12:11:44 -0700174 bool got_ready_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500175 Callback<void(InputData*)> data_callback_;
176 Callback<void(int)> ready_callback_;
Paul Stewart26b327e2011-10-19 11:38:09 -0700177 scoped_ptr<IOHandler> input_handler_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500178 WeakPtrFactory<MockEventDispatchTester> tester_factory_;
179 CancelableClosure failsafe_;
Paul Stewart75897df2011-04-27 09:05:53 -0700180};
181
182class ShillDaemonTest : public Test {
183 public:
184 ShillDaemonTest()
Darin Petkova7b89492011-07-27 12:48:17 -0700185 : daemon_(&config_, new MockControl()),
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800186 metrics_(new MockMetrics(&daemon_.dispatcher_)),
Thieu Lefb46caf2012-03-08 11:57:15 -0800187 manager_(new MockManager(daemon_.control_,
188 &daemon_.dispatcher_,
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800189 metrics_,
Thieu Lefb46caf2012-03-08 11:57:15 -0800190 &daemon_.glib_)),
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800191 device_info_(daemon_.control_, dispatcher_, metrics_,
Thieu Lefb46caf2012-03-08 11:57:15 -0800192 daemon_.manager_.get()),
Darin Petkov887f2982011-07-14 16:10:17 -0700193 dispatcher_(&daemon_.dispatcher_),
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500194 dispatcher_test_(dispatcher_) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700195 }
196 virtual ~ShillDaemonTest() {}
Paul Stewart75897df2011-04-27 09:05:53 -0700197 virtual void SetUp() {
198 // Tests initialization done by the daemon's constructor
Chris Masone0e1d1042011-05-09 18:07:03 -0700199 ASSERT_NE(reinterpret_cast<Config*>(NULL), daemon_.config_);
200 ASSERT_NE(reinterpret_cast<ControlInterface*>(NULL), daemon_.control_);
Thieu Lefb46caf2012-03-08 11:57:15 -0800201 daemon_.proxy_factory_ = &proxy_factory_;
202 daemon_.rtnl_handler_ = &rtnl_handler_;
203 daemon_.routing_table_ = &routing_table_;
204 daemon_.dhcp_provider_ = &dhcp_provider_;
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800205 daemon_.metrics_.reset(metrics_); // Passes ownership
Thieu Lefb46caf2012-03-08 11:57:15 -0800206 daemon_.manager_.reset(manager_); // Passes ownership
Wade Guthriefa2100e2013-05-15 10:11:22 -0700207 daemon_.netlink_manager_ = &netlink_manager_;
Paul Stewartf0aae102011-10-19 12:11:44 -0700208 dispatcher_test_.ScheduleFailSafe();
Wade Guthriefa2100e2013-05-15 10:11:22 -0700209
210 const uint16_t kNl80211MessageType = 42; // Arbitrary.
211 ON_CALL(netlink_manager_, GetFamily(Nl80211Message::kMessageTypeString, _)).
212 WillByDefault(Return(kNl80211MessageType));
Paul Stewart75897df2011-04-27 09:05:53 -0700213 }
Thieu Lefb46caf2012-03-08 11:57:15 -0800214 void StartDaemon() {
215 daemon_.Start();
216 }
217
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800218 void StopDaemon() {
219 daemon_.Stop();
220 }
221
Wade Guthriebb9fca22013-04-10 17:21:42 -0700222 void ResetNetlinkManager() {
223 daemon_.netlink_manager_->Reset(true);
Darin Petkovd5818382013-01-28 16:27:07 +0100224 }
225
Gary Moraina9fb3252012-05-31 12:05:31 -0700226 MOCK_METHOD0(TerminationAction, void());
227
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700228 protected:
Chris Masoneb9c00592011-10-06 13:10:39 -0700229 TestConfig config_;
Paul Stewart75897df2011-04-27 09:05:53 -0700230 Daemon daemon_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800231 MockProxyFactory proxy_factory_;
232 MockRTNLHandler rtnl_handler_;
233 MockRoutingTable routing_table_;
234 MockDHCPProvider dhcp_provider_;
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800235 MockMetrics *metrics_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800236 MockManager *manager_;
Wade Guthriefa2100e2013-05-15 10:11:22 -0700237 MockNetlinkManager netlink_manager_;
Paul Stewart0af98bf2011-05-10 17:38:08 -0700238 DeviceInfo device_info_;
Paul Stewart75897df2011-04-27 09:05:53 -0700239 EventDispatcher *dispatcher_;
240 StrictMock<MockEventDispatchTester> dispatcher_test_;
241};
242
243
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800244TEST_F(ShillDaemonTest, StartStop) {
Thieu Lefb46caf2012-03-08 11:57:15 -0800245 // To ensure we do not have any stale routes, we flush a device's routes
246 // when it is started. This requires that the routing table is fully
247 // populated before we create and start devices. So test to make sure that
248 // the RoutingTable starts before the Manager (which in turn starts
249 // DeviceInfo who is responsible for creating and starting devices).
250 // The result is that we request the dump of the routing table and when that
251 // completes, we request the dump of the links. For each link found, we
252 // create and start the device.
253 EXPECT_CALL(proxy_factory_, Init());
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800254 EXPECT_CALL(*metrics_, Start());
Thieu Lefb46caf2012-03-08 11:57:15 -0800255 EXPECT_CALL(rtnl_handler_, Start(_, _));
256 Expectation routing_table_started = EXPECT_CALL(routing_table_, Start());
257 EXPECT_CALL(dhcp_provider_, Init(_, _, _));
258 EXPECT_CALL(*manager_, Start()).After(routing_table_started);
259 StartDaemon();
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800260 Mock::VerifyAndClearExpectations(metrics_);
261 Mock::VerifyAndClearExpectations(manager_);
262
263 EXPECT_CALL(*manager_, Stop());
264 EXPECT_CALL(*metrics_, Stop());
265 StopDaemon();
Thieu Lefb46caf2012-03-08 11:57:15 -0800266}
267
Paul Stewartf0aae102011-10-19 12:11:44 -0700268TEST_F(ShillDaemonTest, EventDispatcherTimer) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700269 EXPECT_CALL(dispatcher_test_, CallbackComplete(Gt(0)));
270 dispatcher_test_.ScheduleTimedTasks();
271 dispatcher_test_.RescheduleUnlessTriggered();
272 dispatcher_->DispatchForever();
Paul Stewartf0aae102011-10-19 12:11:44 -0700273}
Paul Stewarta43d9232011-05-10 11:40:22 -0700274
Paul Stewartf0aae102011-10-19 12:11:44 -0700275TEST_F(ShillDaemonTest, EventDispatcherIO) {
Paul Stewarta43d9232011-05-10 11:40:22 -0700276 EXPECT_CALL(dispatcher_test_, IOComplete(16));
277 int pipefd[2];
Chris Masone0e1d1042011-05-09 18:07:03 -0700278 ASSERT_EQ(pipe(pipefd), 0);
Paul Stewarta43d9232011-05-10 11:40:22 -0700279
280 dispatcher_test_.ListenIO(pipefd[0]);
Chris Masone0e1d1042011-05-09 18:07:03 -0700281 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
Paul Stewarta43d9232011-05-10 11:40:22 -0700282
Chris Masone0e1d1042011-05-09 18:07:03 -0700283 dispatcher_->DispatchForever();
Paul Stewarta43d9232011-05-10 11:40:22 -0700284 dispatcher_test_.StopListenIO();
Chris Masone0e1d1042011-05-09 18:07:03 -0700285}
286
Paul Stewartf0aae102011-10-19 12:11:44 -0700287TEST_F(ShillDaemonTest, EventDispatcherReady) {
288 EXPECT_CALL(dispatcher_test_, IOComplete(0))
289 .Times(1);
290 EXPECT_CALL(dispatcher_test_, IOComplete(1))
291 .Times(1);
292
293 int pipefd[2];
294 ASSERT_EQ(pipe(pipefd), 0);
295
296 dispatcher_test_.ListenReady(pipefd[0]);
297 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
298
299 dispatcher_->DispatchForever();
300 dispatcher_test_.StopListenReady();
301}
302
Gary Moraina9fb3252012-05-31 12:05:31 -0700303ACTION_P2(CompleteAction, manager, name) {
304 manager->TerminationActionComplete(name);
305}
306
307TEST_F(ShillDaemonTest, Quit) {
308 // The following expectations are to satisfy calls in Daemon::Start().
309 EXPECT_CALL(proxy_factory_, Init());
310 EXPECT_CALL(rtnl_handler_, Start(_, _));
311 EXPECT_CALL(routing_table_, Start());
312 EXPECT_CALL(dhcp_provider_, Init(_, _, _));
313 EXPECT_CALL(*manager_, Start());
314
315 // This expectation verifies that the termination actions are invoked.
316 EXPECT_CALL(*this, TerminationAction())
317 .WillOnce(CompleteAction(manager_, "daemon test"));
318
319 manager_->AddTerminationAction("daemon test",
320 Bind(&ShillDaemonTest::TerminationAction,
321 Unretained(this)));
322
323 // Run Daemon::Quit() after the daemon starts running.
324 dispatcher_->PostTask(Bind(&Daemon::Quit, Unretained(&daemon_)));
Wade Guthriebee87c22013-03-06 11:00:46 -0800325
326 // TODO(wdg): crbug.com/224712 - Need fix for "GLib-WARNING **: Invalid file
Wade Guthriebb9fca22013-04-10 17:21:42 -0700327 // descriptor". This requires support for netlink_manager interface tests.
Gary Moraina9fb3252012-05-31 12:05:31 -0700328 daemon_.Run();
Wade Guthriebb9fca22013-04-10 17:21:42 -0700329 ResetNetlinkManager();
Gary Moraina9fb3252012-05-31 12:05:31 -0700330}
331
Chris Masone9be4a9d2011-05-16 15:44:09 -0700332} // namespace shill