blob: f4f6ca2d6b298724e97c652c32a75ed3cbaa56fc [file] [log] [blame]
Peter Qiu24b34a02015-06-30 10:22:26 -07001// Copyright 2015 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <stdint.h>
6
7#include <memory>
8#include <vector>
9
10#include <base/bind.h>
11#include <base/memory/ref_counted.h>
12#include <gmock/gmock.h>
13#include <gtest/gtest.h>
14
15#include "shill/chromeos_daemon.h"
16#include "shill/dhcp/mock_dhcp_provider.h"
17#include "shill/logging.h"
18#include "shill/mock_control.h"
19#include "shill/mock_manager.h"
20#include "shill/mock_metrics.h"
Peter Qiudde57ef2015-08-14 09:58:51 -070021#include "shill/mock_process_manager.h"
Peter Qiu24b34a02015-06-30 10:22:26 -070022#include "shill/mock_routing_table.h"
23#include "shill/net/io_handler.h"
24#include "shill/net/mock_rtnl_handler.h"
25#include "shill/net/ndisc.h"
26#include "shill/shill_test_config.h"
Peter Qiudde57ef2015-08-14 09:58:51 -070027#include "shill/test_event_dispatcher.h"
Peter Qiu24b34a02015-06-30 10:22:26 -070028
29#if !defined(DISABLE_WIFI)
30#include "shill/net/mock_netlink_manager.h"
31#include "shill/net/nl80211_message.h"
32#endif // DISABLE_WIFI
33
34using base::Bind;
35using base::Callback;
36using base::Unretained;
37using std::string;
38using std::vector;
39
40using ::testing::Expectation;
41using ::testing::Mock;
42using ::testing::Return;
43using ::testing::Test;
44using ::testing::_;
45
46namespace shill {
47
Peter Qiudde57ef2015-08-14 09:58:51 -070048class ChromeosDaemonForTest : public ChromeosDaemon {
Peter Qiu24b34a02015-06-30 10:22:26 -070049 public:
Peter Qiudde57ef2015-08-14 09:58:51 -070050 ChromeosDaemonForTest(const Settings& setttings,
51 Config* config,
52 EventDispatcher* dispatcher)
53 : ChromeosDaemon(Settings(), config) {
54 Init(new MockControl(), dispatcher);
55 }
56 virtual ~ChromeosDaemonForTest() {}
Peter Qiu24b34a02015-06-30 10:22:26 -070057
Peter Qiudde57ef2015-08-14 09:58:51 -070058 void RunMessageLoop() override { dispatcher_->DispatchForever(); }
59
Peter Qiu5988a852015-08-25 16:45:35 -070060 void Quit(const base::Closure& completion_callback) override {
61 ChromeosDaemon::Quit(completion_callback);
Peter Qiudde57ef2015-08-14 09:58:51 -070062 dispatcher_->PostTask(base::MessageLoop::QuitClosure());
63 }
Peter Qiu24b34a02015-06-30 10:22:26 -070064};
65
66class ChromeosDaemonTest : public Test {
67 public:
68 ChromeosDaemonTest()
Peter Qiudde57ef2015-08-14 09:58:51 -070069 : daemon_(ChromeosDaemon::Settings(), &config_, &dispatcher_),
70 metrics_(new MockMetrics(daemon_.dispatcher_)),
Peter Qiu24b34a02015-06-30 10:22:26 -070071 manager_(new MockManager(daemon_.control_.get(),
Peter Qiudde57ef2015-08-14 09:58:51 -070072 daemon_.dispatcher_,
Peter Qiu24b34a02015-06-30 10:22:26 -070073 metrics_,
74 &daemon_.glib_)),
Peter Qiudde57ef2015-08-14 09:58:51 -070075 device_info_(daemon_.control_.get(), daemon_.dispatcher_,
76 metrics_, manager_) {
Peter Qiu24b34a02015-06-30 10:22:26 -070077 }
78 virtual ~ChromeosDaemonTest() {}
79 virtual void SetUp() {
80 // Tests initialization done by the daemon's constructor
81 ASSERT_NE(nullptr, daemon_.config_);
Peter Qiu24b34a02015-06-30 10:22:26 -070082 daemon_.rtnl_handler_ = &rtnl_handler_;
83 daemon_.routing_table_ = &routing_table_;
84 daemon_.dhcp_provider_ = &dhcp_provider_;
Peter Qiudde57ef2015-08-14 09:58:51 -070085 daemon_.process_manager_ = &process_manager_;
Peter Qiu24b34a02015-06-30 10:22:26 -070086 daemon_.metrics_.reset(metrics_); // Passes ownership
87 daemon_.manager_.reset(manager_); // Passes ownership
88
89#if !defined(DISABLE_WIFI)
90 daemon_.netlink_manager_ = &netlink_manager_;
Peter Qiu24b34a02015-06-30 10:22:26 -070091#endif // DISABLE_WIFI
92 }
93 void StartDaemon() {
94 daemon_.Start();
95 }
96
97 void StopDaemon() {
98 daemon_.Stop();
99 }
100
Peter Qiu24b34a02015-06-30 10:22:26 -0700101 void RunDaemon() {
Peter Qiudde57ef2015-08-14 09:58:51 -0700102 daemon_.RunMessageLoop();
Peter Qiu24b34a02015-06-30 10:22:26 -0700103 }
104
105 void ApplySettings(const ChromeosDaemon::Settings& settings) {
Peter Qiudde57ef2015-08-14 09:58:51 -0700106 daemon_.settings_ = settings;
107 daemon_.ApplySettings();
Peter Qiu24b34a02015-06-30 10:22:26 -0700108 }
109
110 MOCK_METHOD0(TerminationAction, void());
Peter Qiu5988a852015-08-25 16:45:35 -0700111 MOCK_METHOD0(TerminationCompleted, void());
Peter Qiu24b34a02015-06-30 10:22:26 -0700112
113 protected:
Peter Qiudde57ef2015-08-14 09:58:51 -0700114 EventDispatcherForTest dispatcher_;
Peter Qiu24b34a02015-06-30 10:22:26 -0700115 TestConfig config_;
Peter Qiudde57ef2015-08-14 09:58:51 -0700116 ChromeosDaemonForTest daemon_;
Peter Qiu24b34a02015-06-30 10:22:26 -0700117 MockRTNLHandler rtnl_handler_;
118 MockRoutingTable routing_table_;
119 MockDHCPProvider dhcp_provider_;
Peter Qiudde57ef2015-08-14 09:58:51 -0700120 MockProcessManager process_manager_;
Peter Qiu24b34a02015-06-30 10:22:26 -0700121 MockMetrics* metrics_;
122 MockManager* manager_;
123#if !defined(DISABLE_WIFI)
124 MockNetlinkManager netlink_manager_;
125#endif // DISABLE_WIFI
Peter Qiu24b34a02015-06-30 10:22:26 -0700126 DeviceInfo device_info_;
127};
128
129TEST_F(ChromeosDaemonTest, StartStop) {
130 // To ensure we do not have any stale routes, we flush a device's routes
131 // when it is started. This requires that the routing table is fully
132 // populated before we create and start devices. So test to make sure that
133 // the RoutingTable starts before the Manager (which in turn starts
134 // DeviceInfo who is responsible for creating and starting devices).
135 // The result is that we request the dump of the routing table and when that
136 // completes, we request the dump of the links. For each link found, we
137 // create and start the device.
138 EXPECT_CALL(*metrics_, Start());
139 EXPECT_CALL(rtnl_handler_, Start(
140 RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
141 RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE | RTMGRP_ND_USEROPT));
142 Expectation routing_table_started = EXPECT_CALL(routing_table_, Start());
Peter Qiudde57ef2015-08-14 09:58:51 -0700143 EXPECT_CALL(dhcp_provider_, Init(_, _, _));
144 EXPECT_CALL(process_manager_, Init(_));
Peter Qiu29875ff2015-08-27 21:24:56 -0700145#if !defined(DISABLE_WIFI)
146 EXPECT_CALL(netlink_manager_, Init());
147 const uint16_t kNl80211MessageType = 42; // Arbitrary.
148 EXPECT_CALL(netlink_manager_,
149 GetFamily(Nl80211Message::kMessageTypeString, _))
150 .WillOnce(Return(kNl80211MessageType));
151 EXPECT_CALL(netlink_manager_, Start());
152#endif // DISABLE_WIFI
Peter Qiu24b34a02015-06-30 10:22:26 -0700153 EXPECT_CALL(*manager_, Start()).After(routing_table_started);
154 StartDaemon();
155 Mock::VerifyAndClearExpectations(metrics_);
156 Mock::VerifyAndClearExpectations(manager_);
157
158 EXPECT_CALL(*manager_, Stop());
159 EXPECT_CALL(*metrics_, Stop());
160 StopDaemon();
161}
162
163ACTION_P2(CompleteAction, manager, name) {
164 manager->TerminationActionComplete(name);
165}
166
167TEST_F(ChromeosDaemonTest, Quit) {
168 // This expectation verifies that the termination actions are invoked.
169 EXPECT_CALL(*this, TerminationAction())
170 .WillOnce(CompleteAction(manager_, "daemon test"));
Peter Qiu5988a852015-08-25 16:45:35 -0700171 EXPECT_CALL(*this, TerminationCompleted()).Times(1);
Peter Qiu24b34a02015-06-30 10:22:26 -0700172
173 manager_->AddTerminationAction("daemon test",
174 Bind(&ChromeosDaemonTest::TerminationAction,
175 Unretained(this)));
176
177 // Run Daemon::Quit() after the daemon starts running.
Peter Qiu5988a852015-08-25 16:45:35 -0700178 dispatcher_.PostTask(
179 Bind(&ChromeosDaemon::Quit,
180 Unretained(&daemon_),
181 Bind(&ChromeosDaemonTest::TerminationCompleted,
182 Unretained(this))));
Peter Qiu24b34a02015-06-30 10:22:26 -0700183
184 RunDaemon();
185}
186
187TEST_F(ChromeosDaemonTest, ApplySettings) {
188 ChromeosDaemon::Settings settings;
189 EXPECT_CALL(*manager_, AddDeviceToBlackList(_)).Times(0);
190 vector<string> kEmptyStringList;
191 EXPECT_CALL(*manager_, SetDHCPv6EnabledDevices(kEmptyStringList));
192 EXPECT_CALL(*manager_, SetTechnologyOrder("", _));
193 EXPECT_CALL(*manager_, SetIgnoreUnknownEthernet(false));
194 EXPECT_CALL(*manager_, SetStartupPortalList(_)).Times(0);
195 EXPECT_CALL(*manager_, SetPassiveMode()).Times(0);
196 EXPECT_CALL(*manager_, SetPrependDNSServers(""));
197 EXPECT_CALL(*manager_, SetMinimumMTU(_)).Times(0);
198 EXPECT_CALL(*manager_, SetAcceptHostnameFrom(""));
199 ApplySettings(settings);
200 Mock::VerifyAndClearExpectations(manager_);
201
202 settings.device_blacklist = {"eth0", "eth1"};
203 settings.default_technology_order = "wifi,ethernet";
204 vector<string> kDHCPv6EnabledDevices {"eth2", "eth3"};
205 settings.dhcpv6_enabled_devices = kDHCPv6EnabledDevices;
206 settings.ignore_unknown_ethernet = false;
207 settings.portal_list = "wimax";
208 settings.use_portal_list = true;
209 settings.passive_mode = true;
210 settings.prepend_dns_servers = "8.8.8.8,8.8.4.4";
211 settings.minimum_mtu = 256;
212 settings.accept_hostname_from = "eth*";
213 EXPECT_CALL(*manager_, AddDeviceToBlackList("eth0"));
214 EXPECT_CALL(*manager_, AddDeviceToBlackList("eth1"));
215 EXPECT_CALL(*manager_, SetDHCPv6EnabledDevices(kDHCPv6EnabledDevices));
216 EXPECT_CALL(*manager_, SetTechnologyOrder("wifi,ethernet", _));
217 EXPECT_CALL(*manager_, SetIgnoreUnknownEthernet(false));
218 EXPECT_CALL(*manager_, SetStartupPortalList("wimax"));
219 EXPECT_CALL(*manager_, SetPassiveMode());
220 EXPECT_CALL(*manager_, SetPrependDNSServers("8.8.8.8,8.8.4.4"));
221 EXPECT_CALL(*manager_, SetMinimumMTU(256));
222 EXPECT_CALL(*manager_, SetAcceptHostnameFrom("eth*"));
223 ApplySettings(settings);
224 Mock::VerifyAndClearExpectations(manager_);
225}
226
227} // namespace shill