Home | History | Annotate | Download | only in shill
      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