1 // 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 // 16 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 27 #include "shill/daemon_task.h" 28 #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" 33 #include "shill/mock_process_manager.h" 34 #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" 39 #include "shill/test_event_dispatcher.h" 40 41 #if !defined(DISABLE_WIFI) 42 #include "shill/net/mock_netlink_manager.h" 43 #include "shill/net/nl80211_message.h" 44 #include "shill/wifi/callback80211_metrics.h" 45 #endif // DISABLE_WIFI 46 47 using base::Bind; 48 using base::Callback; 49 using base::Unretained; 50 using std::string; 51 using std::vector; 52 53 using ::testing::Expectation; 54 using ::testing::Mock; 55 using ::testing::Return; 56 using ::testing::Test; 57 using ::testing::_; 58 59 namespace shill { 60 61 class DaemonTaskForTest : public DaemonTask { 62 public: 63 DaemonTaskForTest(const Settings& setttings, Config* config) 64 : DaemonTask(Settings(), config) {} 65 virtual ~DaemonTaskForTest() {} 66 67 bool quit_result() { return quit_result_; } 68 69 void RunMessageLoop() { dispatcher_->DispatchForever(); } 70 71 bool Quit(const base::Closure& completion_callback) override { 72 quit_result_ = DaemonTask::Quit(completion_callback); 73 dispatcher_->PostTask(base::MessageLoop::QuitWhenIdleClosure()); 74 return quit_result_; 75 } 76 77 private: 78 bool quit_result_; 79 }; 80 81 class DaemonTaskTest : public Test { 82 public: 83 DaemonTaskTest() 84 : daemon_(DaemonTask::Settings(), &config_), 85 dispatcher_(new EventDispatcherForTest()), 86 control_(new MockControl()), 87 metrics_(new MockMetrics(dispatcher_)), 88 manager_(new MockManager(control_, dispatcher_, metrics_)), 89 #if !defined(DISABLE_WIFI) 90 callback_metrics_(new Callback80211Metrics(metrics_)), 91 #endif // DISABLE_WIFI 92 device_info_(control_, dispatcher_, metrics_, manager_) { 93 } 94 virtual ~DaemonTaskTest() {} 95 virtual void SetUp() { 96 // Tests initialization done by the daemon's constructor 97 daemon_.rtnl_handler_ = &rtnl_handler_; 98 daemon_.routing_table_ = &routing_table_; 99 daemon_.dhcp_provider_ = &dhcp_provider_; 100 daemon_.process_manager_ = &process_manager_; 101 daemon_.metrics_.reset(metrics_); // Passes ownership 102 daemon_.manager_.reset(manager_); // Passes ownership 103 daemon_.control_.reset(control_); // Passes ownership 104 daemon_.dispatcher_.reset(dispatcher_); // Passes ownership 105 106 #if !defined(DISABLE_WIFI) 107 daemon_.netlink_manager_ = &netlink_manager_; 108 // Passes ownership 109 daemon_.callback80211_metrics_.reset(callback_metrics_); 110 #endif // DISABLE_WIFI 111 } 112 void StartDaemon() { daemon_.Start(); } 113 114 void StopDaemon() { daemon_.Stop(); } 115 116 void RunDaemon() { daemon_.RunMessageLoop(); } 117 118 void ApplySettings(const DaemonTask::Settings& settings) { 119 daemon_.settings_ = settings; 120 daemon_.ApplySettings(); 121 } 122 123 MOCK_METHOD0(TerminationAction, void()); 124 MOCK_METHOD0(BreakTerminationLoop, void()); 125 126 protected: 127 TestConfig config_; 128 DaemonTaskForTest daemon_; 129 MockRTNLHandler rtnl_handler_; 130 MockRoutingTable routing_table_; 131 MockDHCPProvider dhcp_provider_; 132 MockProcessManager process_manager_; 133 EventDispatcherForTest* dispatcher_; 134 MockControl* control_; 135 MockMetrics* metrics_; 136 MockManager* manager_; 137 #if !defined(DISABLE_WIFI) 138 MockNetlinkManager netlink_manager_; 139 Callback80211Metrics* callback_metrics_; 140 #endif // DISABLE_WIFI 141 DeviceInfo device_info_; 142 }; 143 144 TEST_F(DaemonTaskTest, StartStop) { 145 // 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()); 154 EXPECT_CALL(rtnl_handler_, Start(RTMGRP_LINK | RTMGRP_IPV4_IFADDR | 155 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_IFADDR | 156 RTMGRP_IPV6_ROUTE | RTMGRP_ND_USEROPT)); 157 Expectation routing_table_started = EXPECT_CALL(routing_table_, Start()); 158 EXPECT_CALL(dhcp_provider_, Init(_, _, _)); 159 EXPECT_CALL(process_manager_, Init(_)); 160 #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 168 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()); 175 EXPECT_CALL(process_manager_, Stop()); 176 StopDaemon(); 177 } 178 179 ACTION_P2(CompleteAction, manager, name) { 180 manager->TerminationActionComplete(name); 181 } 182 183 TEST_F(DaemonTaskTest, QuitWithTerminationAction) { 184 // This expectation verifies that the termination actions are invoked. 185 EXPECT_CALL(*this, TerminationAction()) 186 .WillOnce(CompleteAction(manager_, "daemon test")); 187 EXPECT_CALL(*this, BreakTerminationLoop()).Times(1); 188 189 manager_->AddTerminationAction( 190 "daemon test", 191 Bind(&DaemonTaskTest::TerminationAction, Unretained(this))); 192 193 // Run Daemon::Quit() after the daemon starts running. 194 dispatcher_->PostTask( 195 Bind(IgnoreResult(&DaemonTask::Quit), Unretained(&daemon_), 196 Bind(&DaemonTaskTest::BreakTerminationLoop, Unretained(this)))); 197 198 RunDaemon(); 199 EXPECT_FALSE(daemon_.quit_result()); 200 } 201 202 TEST_F(DaemonTaskTest, QuitWithoutTerminationActions) { 203 EXPECT_CALL(*this, BreakTerminationLoop()).Times(0); 204 EXPECT_TRUE(daemon_.Quit( 205 Bind(&DaemonTaskTest::BreakTerminationLoop, Unretained(this)))); 206 } 207 208 TEST_F(DaemonTaskTest, ApplySettings) { 209 DaemonTask::Settings settings; 210 vector<string> kEmptyStringList; 211 EXPECT_CALL(*manager_, SetBlacklistedDevices(kEmptyStringList)); 212 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 223 vector<string> kBlacklistedDevices = {"eth0", "eth1"}; 224 settings.device_blacklist = kBlacklistedDevices; 225 settings.default_technology_order = "wifi,ethernet"; 226 vector<string> kDHCPv6EnabledDevices{"eth2", "eth3"}; 227 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*"; 235 EXPECT_CALL(*manager_, SetBlacklistedDevices(kBlacklistedDevices)); 236 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 249