blob: d7fe41c8c91e8f7ad8b3b426ce0c0766c5104d15 [file] [log] [blame]
Peter Qiuc0beca52015-09-03 11:25:46 -07001//
2// Copyright (C) 2015 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Peter Qiu24b34a02015-06-30 10:22:26 -070016
17#include <stdint.h>
18
19#include <memory>
20#include <vector>
21
22#include <base/bind.h>
23#include <base/memory/ref_counted.h>
24#include <gmock/gmock.h>
25#include <gtest/gtest.h>
26
Samuel Tan59b397b2016-01-20 11:25:21 -080027#include "shill/daemon_task.h"
Peter Qiu24b34a02015-06-30 10:22:26 -070028#include "shill/dhcp/mock_dhcp_provider.h"
29#include "shill/logging.h"
30#include "shill/mock_control.h"
31#include "shill/mock_manager.h"
32#include "shill/mock_metrics.h"
Peter Qiudde57ef2015-08-14 09:58:51 -070033#include "shill/mock_process_manager.h"
Peter Qiu24b34a02015-06-30 10:22:26 -070034#include "shill/mock_routing_table.h"
35#include "shill/net/io_handler.h"
36#include "shill/net/mock_rtnl_handler.h"
37#include "shill/net/ndisc.h"
38#include "shill/shill_test_config.h"
Peter Qiudde57ef2015-08-14 09:58:51 -070039#include "shill/test_event_dispatcher.h"
Peter Qiu24b34a02015-06-30 10:22:26 -070040
41#if !defined(DISABLE_WIFI)
42#include "shill/net/mock_netlink_manager.h"
43#include "shill/net/nl80211_message.h"
Samuel Tan646c7e82015-12-28 15:43:46 -080044#include "shill/wifi/callback80211_metrics.h"
Peter Qiu24b34a02015-06-30 10:22:26 -070045#endif // DISABLE_WIFI
46
47using base::Bind;
48using base::Callback;
49using base::Unretained;
50using std::string;
51using std::vector;
52
53using ::testing::Expectation;
54using ::testing::Mock;
55using ::testing::Return;
56using ::testing::Test;
57using ::testing::_;
58
59namespace shill {
60
Samuel Tan59b397b2016-01-20 11:25:21 -080061class DaemonTaskForTest : public DaemonTask {
Peter Qiu24b34a02015-06-30 10:22:26 -070062 public:
Samuel Tan59b397b2016-01-20 11:25:21 -080063 DaemonTaskForTest(const Settings& setttings, Config* config)
64 : DaemonTask(Settings(), config) {}
65 virtual ~DaemonTaskForTest() {}
Peter Qiu24b34a02015-06-30 10:22:26 -070066
mukesh agrawale6b41922015-09-24 16:52:14 -070067 bool quit_result() { return quit_result_; }
68
Samuel Tan646c7e82015-12-28 15:43:46 -080069 void RunMessageLoop() { dispatcher_->DispatchForever(); }
Peter Qiudde57ef2015-08-14 09:58:51 -070070
mukesh agrawale6b41922015-09-24 16:52:14 -070071 bool Quit(const base::Closure& completion_callback) override {
Samuel Tan59b397b2016-01-20 11:25:21 -080072 quit_result_ = DaemonTask::Quit(completion_callback);
Alex Vakulenko3a62e232016-01-20 07:47:40 -080073 dispatcher_->PostTask(base::MessageLoop::QuitWhenIdleClosure());
mukesh agrawale6b41922015-09-24 16:52:14 -070074 return quit_result_;
Peter Qiudde57ef2015-08-14 09:58:51 -070075 }
mukesh agrawale6b41922015-09-24 16:52:14 -070076
77 private:
78 bool quit_result_;
Peter Qiu24b34a02015-06-30 10:22:26 -070079};
80
Samuel Tan59b397b2016-01-20 11:25:21 -080081class DaemonTaskTest : public Test {
Peter Qiu24b34a02015-06-30 10:22:26 -070082 public:
Samuel Tan59b397b2016-01-20 11:25:21 -080083 DaemonTaskTest()
84 : daemon_(DaemonTask::Settings(), &config_),
Samuel Tan646c7e82015-12-28 15:43:46 -080085 dispatcher_(new EventDispatcherForTest()),
86 control_(new MockControl()),
87 metrics_(new MockMetrics(dispatcher_)),
Samuel Tan59b397b2016-01-20 11:25:21 -080088 manager_(new MockManager(control_, dispatcher_, metrics_)),
Samuel Tan7370e4f2016-01-07 15:25:23 -080089#if !defined(DISABLE_WIFI)
90 callback_metrics_(new Callback80211Metrics(metrics_)),
91#endif // DISABLE_WIFI
Samuel Tan59b397b2016-01-20 11:25:21 -080092 device_info_(control_, dispatcher_, metrics_, manager_) {
93 }
94 virtual ~DaemonTaskTest() {}
Peter Qiu24b34a02015-06-30 10:22:26 -070095 virtual void SetUp() {
96 // Tests initialization done by the daemon's constructor
Peter Qiu24b34a02015-06-30 10:22:26 -070097 daemon_.rtnl_handler_ = &rtnl_handler_;
98 daemon_.routing_table_ = &routing_table_;
99 daemon_.dhcp_provider_ = &dhcp_provider_;
Peter Qiudde57ef2015-08-14 09:58:51 -0700100 daemon_.process_manager_ = &process_manager_;
Samuel Tan59b397b2016-01-20 11:25:21 -0800101 daemon_.metrics_.reset(metrics_); // Passes ownership
102 daemon_.manager_.reset(manager_); // Passes ownership
103 daemon_.control_.reset(control_); // Passes ownership
Samuel Tan646c7e82015-12-28 15:43:46 -0800104 daemon_.dispatcher_.reset(dispatcher_); // Passes ownership
Peter Qiu24b34a02015-06-30 10:22:26 -0700105
106#if !defined(DISABLE_WIFI)
107 daemon_.netlink_manager_ = &netlink_manager_;
Samuel Tan7370e4f2016-01-07 15:25:23 -0800108 // Passes ownership
109 daemon_.callback80211_metrics_.reset(callback_metrics_);
Peter Qiu24b34a02015-06-30 10:22:26 -0700110#endif // DISABLE_WIFI
111 }
Samuel Tan59b397b2016-01-20 11:25:21 -0800112 void StartDaemon() { daemon_.Start(); }
Peter Qiu24b34a02015-06-30 10:22:26 -0700113
Samuel Tan59b397b2016-01-20 11:25:21 -0800114 void StopDaemon() { daemon_.Stop(); }
Peter Qiu24b34a02015-06-30 10:22:26 -0700115
Samuel Tan59b397b2016-01-20 11:25:21 -0800116 void RunDaemon() { daemon_.RunMessageLoop(); }
Peter Qiu24b34a02015-06-30 10:22:26 -0700117
Samuel Tan59b397b2016-01-20 11:25:21 -0800118 void ApplySettings(const DaemonTask::Settings& settings) {
Peter Qiudde57ef2015-08-14 09:58:51 -0700119 daemon_.settings_ = settings;
120 daemon_.ApplySettings();
Peter Qiu24b34a02015-06-30 10:22:26 -0700121 }
122
123 MOCK_METHOD0(TerminationAction, void());
Samuel Tan646c7e82015-12-28 15:43:46 -0800124 MOCK_METHOD0(BreakTerminationLoop, void());
Peter Qiu24b34a02015-06-30 10:22:26 -0700125
126 protected:
127 TestConfig config_;
Samuel Tan59b397b2016-01-20 11:25:21 -0800128 DaemonTaskForTest daemon_;
Peter Qiu24b34a02015-06-30 10:22:26 -0700129 MockRTNLHandler rtnl_handler_;
130 MockRoutingTable routing_table_;
131 MockDHCPProvider dhcp_provider_;
Peter Qiudde57ef2015-08-14 09:58:51 -0700132 MockProcessManager process_manager_;
Samuel Tan646c7e82015-12-28 15:43:46 -0800133 EventDispatcherForTest* dispatcher_;
134 MockControl* control_;
Peter Qiu24b34a02015-06-30 10:22:26 -0700135 MockMetrics* metrics_;
136 MockManager* manager_;
137#if !defined(DISABLE_WIFI)
138 MockNetlinkManager netlink_manager_;
Samuel Tan7370e4f2016-01-07 15:25:23 -0800139 Callback80211Metrics* callback_metrics_;
Peter Qiu24b34a02015-06-30 10:22:26 -0700140#endif // DISABLE_WIFI
Peter Qiu24b34a02015-06-30 10:22:26 -0700141 DeviceInfo device_info_;
142};
143
Samuel Tan59b397b2016-01-20 11:25:21 -0800144TEST_F(DaemonTaskTest, StartStop) {
Peter Qiu24b34a02015-06-30 10:22:26 -0700145 // To ensure we do not have any stale routes, we flush a device's routes
146 // when it is started. This requires that the routing table is fully
147 // populated before we create and start devices. So test to make sure that
148 // the RoutingTable starts before the Manager (which in turn starts
149 // DeviceInfo who is responsible for creating and starting devices).
150 // The result is that we request the dump of the routing table and when that
151 // completes, we request the dump of the links. For each link found, we
152 // create and start the device.
153 EXPECT_CALL(*metrics_, Start());
Samuel Tan59b397b2016-01-20 11:25:21 -0800154 EXPECT_CALL(rtnl_handler_, Start(RTMGRP_LINK | RTMGRP_IPV4_IFADDR |
155 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_IFADDR |
156 RTMGRP_IPV6_ROUTE | RTMGRP_ND_USEROPT));
Peter Qiu24b34a02015-06-30 10:22:26 -0700157 Expectation routing_table_started = EXPECT_CALL(routing_table_, Start());
Samuel Tan59b397b2016-01-20 11:25:21 -0800158 EXPECT_CALL(dhcp_provider_, Init(_, _, _));
Peter Qiudde57ef2015-08-14 09:58:51 -0700159 EXPECT_CALL(process_manager_, Init(_));
Peter Qiu29875ff2015-08-27 21:24:56 -0700160#if !defined(DISABLE_WIFI)
161 EXPECT_CALL(netlink_manager_, Init());
162 const uint16_t kNl80211MessageType = 42; // Arbitrary.
163 EXPECT_CALL(netlink_manager_,
164 GetFamily(Nl80211Message::kMessageTypeString, _))
165 .WillOnce(Return(kNl80211MessageType));
166 EXPECT_CALL(netlink_manager_, Start());
167#endif // DISABLE_WIFI
Peter Qiu24b34a02015-06-30 10:22:26 -0700168 EXPECT_CALL(*manager_, Start()).After(routing_table_started);
169 StartDaemon();
170 Mock::VerifyAndClearExpectations(metrics_);
171 Mock::VerifyAndClearExpectations(manager_);
172
173 EXPECT_CALL(*manager_, Stop());
174 EXPECT_CALL(*metrics_, Stop());
Peter Qiu89dfada2015-09-16 12:04:07 -0700175 EXPECT_CALL(process_manager_, Stop());
Peter Qiu24b34a02015-06-30 10:22:26 -0700176 StopDaemon();
177}
178
179ACTION_P2(CompleteAction, manager, name) {
180 manager->TerminationActionComplete(name);
181}
182
Samuel Tan59b397b2016-01-20 11:25:21 -0800183TEST_F(DaemonTaskTest, QuitWithTerminationAction) {
Peter Qiu24b34a02015-06-30 10:22:26 -0700184 // This expectation verifies that the termination actions are invoked.
185 EXPECT_CALL(*this, TerminationAction())
186 .WillOnce(CompleteAction(manager_, "daemon test"));
Samuel Tan646c7e82015-12-28 15:43:46 -0800187 EXPECT_CALL(*this, BreakTerminationLoop()).Times(1);
Peter Qiu24b34a02015-06-30 10:22:26 -0700188
Samuel Tan59b397b2016-01-20 11:25:21 -0800189 manager_->AddTerminationAction(
190 "daemon test",
191 Bind(&DaemonTaskTest::TerminationAction, Unretained(this)));
Peter Qiu24b34a02015-06-30 10:22:26 -0700192
193 // Run Daemon::Quit() after the daemon starts running.
Samuel Tan646c7e82015-12-28 15:43:46 -0800194 dispatcher_->PostTask(
Samuel Tan59b397b2016-01-20 11:25:21 -0800195 Bind(IgnoreResult(&DaemonTask::Quit), Unretained(&daemon_),
196 Bind(&DaemonTaskTest::BreakTerminationLoop, Unretained(this))));
Peter Qiu24b34a02015-06-30 10:22:26 -0700197
198 RunDaemon();
mukesh agrawale6b41922015-09-24 16:52:14 -0700199 EXPECT_FALSE(daemon_.quit_result());
200}
201
Samuel Tan59b397b2016-01-20 11:25:21 -0800202TEST_F(DaemonTaskTest, QuitWithoutTerminationActions) {
Samuel Tan646c7e82015-12-28 15:43:46 -0800203 EXPECT_CALL(*this, BreakTerminationLoop()).Times(0);
mukesh agrawale6b41922015-09-24 16:52:14 -0700204 EXPECT_TRUE(daemon_.Quit(
Samuel Tan59b397b2016-01-20 11:25:21 -0800205 Bind(&DaemonTaskTest::BreakTerminationLoop, Unretained(this))));
Peter Qiu24b34a02015-06-30 10:22:26 -0700206}
207
Samuel Tan59b397b2016-01-20 11:25:21 -0800208TEST_F(DaemonTaskTest, ApplySettings) {
209 DaemonTask::Settings settings;
Peter Qiu24b34a02015-06-30 10:22:26 -0700210 vector<string> kEmptyStringList;
Peter Qiu91b71502015-11-09 13:55:18 -0800211 EXPECT_CALL(*manager_, SetBlacklistedDevices(kEmptyStringList));
Peter Qiu24b34a02015-06-30 10:22:26 -0700212 EXPECT_CALL(*manager_, SetDHCPv6EnabledDevices(kEmptyStringList));
213 EXPECT_CALL(*manager_, SetTechnologyOrder("", _));
214 EXPECT_CALL(*manager_, SetIgnoreUnknownEthernet(false));
215 EXPECT_CALL(*manager_, SetStartupPortalList(_)).Times(0);
216 EXPECT_CALL(*manager_, SetPassiveMode()).Times(0);
217 EXPECT_CALL(*manager_, SetPrependDNSServers(""));
218 EXPECT_CALL(*manager_, SetMinimumMTU(_)).Times(0);
219 EXPECT_CALL(*manager_, SetAcceptHostnameFrom(""));
220 ApplySettings(settings);
221 Mock::VerifyAndClearExpectations(manager_);
222
Peter Qiu91b71502015-11-09 13:55:18 -0800223 vector<string> kBlacklistedDevices = {"eth0", "eth1"};
224 settings.device_blacklist = kBlacklistedDevices;
Peter Qiu24b34a02015-06-30 10:22:26 -0700225 settings.default_technology_order = "wifi,ethernet";
Samuel Tan59b397b2016-01-20 11:25:21 -0800226 vector<string> kDHCPv6EnabledDevices{"eth2", "eth3"};
Peter Qiu24b34a02015-06-30 10:22:26 -0700227 settings.dhcpv6_enabled_devices = kDHCPv6EnabledDevices;
228 settings.ignore_unknown_ethernet = false;
229 settings.portal_list = "wimax";
230 settings.use_portal_list = true;
231 settings.passive_mode = true;
232 settings.prepend_dns_servers = "8.8.8.8,8.8.4.4";
233 settings.minimum_mtu = 256;
234 settings.accept_hostname_from = "eth*";
Peter Qiu91b71502015-11-09 13:55:18 -0800235 EXPECT_CALL(*manager_, SetBlacklistedDevices(kBlacklistedDevices));
Peter Qiu24b34a02015-06-30 10:22:26 -0700236 EXPECT_CALL(*manager_, SetDHCPv6EnabledDevices(kDHCPv6EnabledDevices));
237 EXPECT_CALL(*manager_, SetTechnologyOrder("wifi,ethernet", _));
238 EXPECT_CALL(*manager_, SetIgnoreUnknownEthernet(false));
239 EXPECT_CALL(*manager_, SetStartupPortalList("wimax"));
240 EXPECT_CALL(*manager_, SetPassiveMode());
241 EXPECT_CALL(*manager_, SetPrependDNSServers("8.8.8.8,8.8.4.4"));
242 EXPECT_CALL(*manager_, SetMinimumMTU(256));
243 EXPECT_CALL(*manager_, SetAcceptHostnameFrom("eth*"));
244 ApplySettings(settings);
245 Mock::VerifyAndClearExpectations(manager_);
246}
247
248} // namespace shill