blob: dc3d3e7910ee0e4fe7d94daeb7c04c5dd0f3969f [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 Masoneee929b72011-05-10 10:02:18 -07009#include <base/logging.h>
Chris Masone487b8bf2011-05-13 16:27:57 -070010#include <base/memory/ref_counted.h>
Chris Masone0e1d1042011-05-09 18:07:03 -070011#include <base/message_loop_proxy.h>
12#include <base/stringprintf.h>
Chris Masoneee929b72011-05-10 10:02:18 -070013#include <gmock/gmock.h>
Darin Petkov887f2982011-07-14 16:10:17 -070014#include <gtest/gtest.h>
Chris Masoneee929b72011-05-10 10:02:18 -070015
Darin Petkov67d8ecf2011-07-26 16:03:30 -070016#include "shill/io_handler.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;
29using base::WeakPtrFactory;
30
Thieu Lefb46caf2012-03-08 11:57:15 -080031using ::testing::Expectation;
Chris Masone0e1d1042011-05-09 18:07:03 -070032using ::testing::Gt;
Paul Stewart75897df2011-04-27 09:05:53 -070033using ::testing::NotNull;
34using ::testing::Return;
Paul Stewart75897df2011-04-27 09:05:53 -070035using ::testing::StrictMock;
Thieu Lefb46caf2012-03-08 11:57:15 -080036using ::testing::Test;
37using ::testing::_;
38
39namespace shill {
Paul Stewart75897df2011-04-27 09:05:53 -070040
41class MockEventDispatchTester {
42 public:
43 explicit MockEventDispatchTester(EventDispatcher *dispatcher)
Chris Masone0e1d1042011-05-09 18:07:03 -070044 : dispatcher_(dispatcher),
45 triggered_(false),
46 callback_count_(0),
47 got_data_(false),
Paul Stewartf0aae102011-10-19 12:11:44 -070048 got_ready_(false),
Chris Masone0e1d1042011-05-09 18:07:03 -070049 input_handler_(NULL),
50 tester_factory_(this) {
Paul Stewart75897df2011-04-27 09:05:53 -070051 }
52
Paul Stewartf0aae102011-10-19 12:11:44 -070053 void ScheduleFailSafe() {
54 // Set up a failsafe, so the test still exits even if something goes
Eric Shienbrood3e20a232012-02-16 11:35:56 -050055 // wrong.
56 failsafe_.Reset(Bind(&MockEventDispatchTester::StopDispatcher,
57 tester_factory_.GetWeakPtr()));
58 dispatcher_->PostDelayedTask(failsafe_.callback(), 100);
Paul Stewartf0aae102011-10-19 12:11:44 -070059 }
60
Chris Masone0e1d1042011-05-09 18:07:03 -070061 void ScheduleTimedTasks() {
62 dispatcher_->PostDelayedTask(
Eric Shienbrood3e20a232012-02-16 11:35:56 -050063 Bind(&MockEventDispatchTester::Trigger, tester_factory_.GetWeakPtr()),
Chris Masone0e1d1042011-05-09 18:07:03 -070064 10);
Paul Stewart75897df2011-04-27 09:05:53 -070065 }
66
Chris Masone0e1d1042011-05-09 18:07:03 -070067 void RescheduleUnlessTriggered() {
68 ++callback_count_;
Paul Stewart75897df2011-04-27 09:05:53 -070069 if (!triggered_) {
Chris Masone0e1d1042011-05-09 18:07:03 -070070 dispatcher_->PostTask(
Eric Shienbrood3e20a232012-02-16 11:35:56 -050071 Bind(&MockEventDispatchTester::RescheduleUnlessTriggered,
72 tester_factory_.GetWeakPtr()));
Chris Masone0e1d1042011-05-09 18:07:03 -070073 } else {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050074 failsafe_.Cancel();
Paul Stewartf0aae102011-10-19 12:11:44 -070075 StopDispatcher();
Paul Stewart75897df2011-04-27 09:05:53 -070076 }
77 }
78
Paul Stewartf0aae102011-10-19 12:11:44 -070079 void StopDispatcher() {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050080 dispatcher_->PostTask(MessageLoop::QuitClosure());
Chris Masone0e1d1042011-05-09 18:07:03 -070081 }
Paul Stewart75897df2011-04-27 09:05:53 -070082
Chris Masone0e1d1042011-05-09 18:07:03 -070083 void Trigger() {
84 LOG(INFO) << "MockEventDispatchTester handling " << callback_count_;
85 CallbackComplete(callback_count_);
86 triggered_ = true;
87 }
Paul Stewarta43d9232011-05-10 11:40:22 -070088
89 void HandleData(InputData *inputData) {
Chris Masone0e1d1042011-05-09 18:07:03 -070090 LOG(INFO) << "MockEventDispatchTester handling data len "
Paul Stewart83224402011-11-30 14:52:30 -080091 << base::StringPrintf("%zd %.*s", inputData->len,
92 static_cast<int>(inputData->len),
93 inputData->buf);
Paul Stewarta43d9232011-05-10 11:40:22 -070094 got_data_ = true;
95 IOComplete(inputData->len);
Paul Stewartf0aae102011-10-19 12:11:44 -070096 StopDispatcher();
Paul Stewarta43d9232011-05-10 11:40:22 -070097 }
Chris Masone0e1d1042011-05-09 18:07:03 -070098
Paul Stewarta43d9232011-05-10 11:40:22 -070099 bool GetData() { return got_data_; }
100
101 void ListenIO(int fd) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500102 data_callback_ = Bind(&MockEventDispatchTester::HandleData,
103 tester_factory_.GetWeakPtr());
Paul Stewartf0aae102011-10-19 12:11:44 -0700104 input_handler_.reset(
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500105 dispatcher_->CreateInputHandler(fd, data_callback_));
Paul Stewarta43d9232011-05-10 11:40:22 -0700106 }
107
108 void StopListenIO() {
109 got_data_ = false;
Chris Masone0e1d1042011-05-09 18:07:03 -0700110 input_handler_.reset(NULL);
Paul Stewarta43d9232011-05-10 11:40:22 -0700111 }
112
Paul Stewartf0aae102011-10-19 12:11:44 -0700113 void HandleReady(int fd) {
114 // Stop event handling after we receive in input-ready event. We should
115 // no longer be called until events are re-enabled.
116 input_handler_->Stop();
117
118 if (got_ready_) {
119 // If we're still getting events after we have stopped them, something
120 // is really wrong, and we cannot just depend on ASSERT_FALSE() to get
121 // us out of it. Make sure the dispatcher is also stopped, or else we
122 // could end up never exiting.
123 StopDispatcher();
124 ASSERT_FALSE(got_ready_) << "failed to stop Input Ready events";
125 }
126 got_ready_ = true;
127
128 LOG(INFO) << "MockEventDispatchTester handling ready for fd " << fd;
129 IOComplete(callback_count_);
130
131 if (callback_count_) {
132 StopDispatcher();
133 } else {
134 // Restart Ready events after 10 millisecond delay.
135 callback_count_++;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500136 dispatcher_->PostDelayedTask(
137 Bind(&MockEventDispatchTester::RestartReady,
138 tester_factory_.GetWeakPtr()),
139 10);
Paul Stewartf0aae102011-10-19 12:11:44 -0700140 }
141 }
142
143 void RestartReady() {
144 got_ready_ = false;
145 input_handler_->Start();
146 }
147
148 void ListenReady(int fd) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500149 ready_callback_ = Bind(&MockEventDispatchTester::HandleReady,
150 tester_factory_.GetWeakPtr());
Paul Stewartf0aae102011-10-19 12:11:44 -0700151 input_handler_.reset(
152 dispatcher_->CreateReadyHandler(fd, IOHandler::kModeInput,
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500153 ready_callback_));
Paul Stewartf0aae102011-10-19 12:11:44 -0700154 }
155
156 void StopListenReady() {
157 got_ready_ = false;
158 input_handler_.reset(NULL);
159 }
160
Paul Stewart75897df2011-04-27 09:05:53 -0700161 MOCK_METHOD1(CallbackComplete, void(int));
Paul Stewarta43d9232011-05-10 11:40:22 -0700162 MOCK_METHOD1(IOComplete, void(int));
Paul Stewart26b327e2011-10-19 11:38:09 -0700163
Paul Stewart75897df2011-04-27 09:05:53 -0700164 private:
Paul Stewarta43d9232011-05-10 11:40:22 -0700165 EventDispatcher *dispatcher_;
Paul Stewart75897df2011-04-27 09:05:53 -0700166 bool triggered_;
Chris Masone0e1d1042011-05-09 18:07:03 -0700167 int callback_count_;
Paul Stewarta43d9232011-05-10 11:40:22 -0700168 bool got_data_;
Paul Stewartf0aae102011-10-19 12:11:44 -0700169 bool got_ready_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500170 Callback<void(InputData*)> data_callback_;
171 Callback<void(int)> ready_callback_;
Paul Stewart26b327e2011-10-19 11:38:09 -0700172 scoped_ptr<IOHandler> input_handler_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500173 WeakPtrFactory<MockEventDispatchTester> tester_factory_;
174 CancelableClosure failsafe_;
Paul Stewart75897df2011-04-27 09:05:53 -0700175};
176
177class ShillDaemonTest : public Test {
178 public:
179 ShillDaemonTest()
Darin Petkova7b89492011-07-27 12:48:17 -0700180 : daemon_(&config_, new MockControl()),
Thieu Lefb46caf2012-03-08 11:57:15 -0800181 manager_(new MockManager(daemon_.control_,
182 &daemon_.dispatcher_,
183 &daemon_.metrics_,
184 &daemon_.glib_)),
Thieu Le3426c8f2012-01-11 17:35:11 -0800185 device_info_(daemon_.control_, dispatcher_, &daemon_.metrics_,
Thieu Lefb46caf2012-03-08 11:57:15 -0800186 daemon_.manager_.get()),
Darin Petkov887f2982011-07-14 16:10:17 -0700187 dispatcher_(&daemon_.dispatcher_),
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500188 dispatcher_test_(dispatcher_) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700189 }
190 virtual ~ShillDaemonTest() {}
Paul Stewart75897df2011-04-27 09:05:53 -0700191 virtual void SetUp() {
192 // Tests initialization done by the daemon's constructor
Chris Masone0e1d1042011-05-09 18:07:03 -0700193 ASSERT_NE(reinterpret_cast<Config*>(NULL), daemon_.config_);
194 ASSERT_NE(reinterpret_cast<ControlInterface*>(NULL), daemon_.control_);
Thieu Lefb46caf2012-03-08 11:57:15 -0800195 daemon_.proxy_factory_ = &proxy_factory_;
196 daemon_.rtnl_handler_ = &rtnl_handler_;
197 daemon_.routing_table_ = &routing_table_;
198 daemon_.dhcp_provider_ = &dhcp_provider_;
199 daemon_.manager_.reset(manager_); // Passes ownership
Paul Stewartf0aae102011-10-19 12:11:44 -0700200 dispatcher_test_.ScheduleFailSafe();
Paul Stewart75897df2011-04-27 09:05:53 -0700201 }
Thieu Lefb46caf2012-03-08 11:57:15 -0800202 void StartDaemon() {
203 daemon_.Start();
204 }
205
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700206 protected:
Chris Masoneb9c00592011-10-06 13:10:39 -0700207 TestConfig config_;
Paul Stewart75897df2011-04-27 09:05:53 -0700208 Daemon daemon_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800209 MockProxyFactory proxy_factory_;
210 MockRTNLHandler rtnl_handler_;
211 MockRoutingTable routing_table_;
212 MockDHCPProvider dhcp_provider_;
213 MockManager *manager_;
Paul Stewart0af98bf2011-05-10 17:38:08 -0700214 DeviceInfo device_info_;
Paul Stewart75897df2011-04-27 09:05:53 -0700215 EventDispatcher *dispatcher_;
216 StrictMock<MockEventDispatchTester> dispatcher_test_;
217};
218
219
Thieu Lefb46caf2012-03-08 11:57:15 -0800220TEST_F(ShillDaemonTest, Start) {
221 // To ensure we do not have any stale routes, we flush a device's routes
222 // when it is started. This requires that the routing table is fully
223 // populated before we create and start devices. So test to make sure that
224 // the RoutingTable starts before the Manager (which in turn starts
225 // DeviceInfo who is responsible for creating and starting devices).
226 // The result is that we request the dump of the routing table and when that
227 // completes, we request the dump of the links. For each link found, we
228 // create and start the device.
229 EXPECT_CALL(proxy_factory_, Init());
230 EXPECT_CALL(rtnl_handler_, Start(_, _));
231 Expectation routing_table_started = EXPECT_CALL(routing_table_, Start());
232 EXPECT_CALL(dhcp_provider_, Init(_, _, _));
233 EXPECT_CALL(*manager_, Start()).After(routing_table_started);
234 StartDaemon();
235}
236
Paul Stewartf0aae102011-10-19 12:11:44 -0700237TEST_F(ShillDaemonTest, EventDispatcherTimer) {
Chris Masone0e1d1042011-05-09 18:07:03 -0700238 EXPECT_CALL(dispatcher_test_, CallbackComplete(Gt(0)));
239 dispatcher_test_.ScheduleTimedTasks();
240 dispatcher_test_.RescheduleUnlessTriggered();
241 dispatcher_->DispatchForever();
Paul Stewartf0aae102011-10-19 12:11:44 -0700242}
Paul Stewarta43d9232011-05-10 11:40:22 -0700243
Paul Stewartf0aae102011-10-19 12:11:44 -0700244TEST_F(ShillDaemonTest, EventDispatcherIO) {
Paul Stewarta43d9232011-05-10 11:40:22 -0700245 EXPECT_CALL(dispatcher_test_, IOComplete(16));
246 int pipefd[2];
Chris Masone0e1d1042011-05-09 18:07:03 -0700247 ASSERT_EQ(pipe(pipefd), 0);
Paul Stewarta43d9232011-05-10 11:40:22 -0700248
249 dispatcher_test_.ListenIO(pipefd[0]);
Chris Masone0e1d1042011-05-09 18:07:03 -0700250 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
Paul Stewarta43d9232011-05-10 11:40:22 -0700251
Chris Masone0e1d1042011-05-09 18:07:03 -0700252 dispatcher_->DispatchForever();
Paul Stewarta43d9232011-05-10 11:40:22 -0700253 dispatcher_test_.StopListenIO();
Chris Masone0e1d1042011-05-09 18:07:03 -0700254}
255
Paul Stewartf0aae102011-10-19 12:11:44 -0700256TEST_F(ShillDaemonTest, EventDispatcherReady) {
257 EXPECT_CALL(dispatcher_test_, IOComplete(0))
258 .Times(1);
259 EXPECT_CALL(dispatcher_test_, IOComplete(1))
260 .Times(1);
261
262 int pipefd[2];
263 ASSERT_EQ(pipe(pipefd), 0);
264
265 dispatcher_test_.ListenReady(pipefd[0]);
266 ASSERT_EQ(write(pipefd[1], "This is a test?!", 16), 16);
267
268 dispatcher_->DispatchForever();
269 dispatcher_test_.StopListenReady();
270}
271
Chris Masone9be4a9d2011-05-16 15:44:09 -0700272} // namespace shill