248 lines
8.6 KiB
C++
248 lines
8.6 KiB
C++
//
|
|
// Copyright (C) 2015 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include <base/bind.h>
|
|
#include <base/memory/ref_counted.h>
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "shill/daemon_task.h"
|
|
#include "shill/dhcp/mock_dhcp_provider.h"
|
|
#include "shill/logging.h"
|
|
#include "shill/mock_control.h"
|
|
#include "shill/mock_manager.h"
|
|
#include "shill/mock_metrics.h"
|
|
#include "shill/mock_process_manager.h"
|
|
#include "shill/mock_routing_table.h"
|
|
#include "shill/net/io_handler.h"
|
|
#include "shill/net/mock_rtnl_handler.h"
|
|
#include "shill/net/ndisc.h"
|
|
#include "shill/shill_test_config.h"
|
|
#include "shill/test_event_dispatcher.h"
|
|
|
|
#if !defined(DISABLE_WIFI)
|
|
#include "shill/net/mock_netlink_manager.h"
|
|
#include "shill/net/nl80211_message.h"
|
|
#include "shill/wifi/callback80211_metrics.h"
|
|
#endif // DISABLE_WIFI
|
|
|
|
using base::Bind;
|
|
using base::Callback;
|
|
using base::Unretained;
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
using ::testing::Expectation;
|
|
using ::testing::Mock;
|
|
using ::testing::Return;
|
|
using ::testing::Test;
|
|
using ::testing::_;
|
|
|
|
namespace shill {
|
|
|
|
class DaemonTaskForTest : public DaemonTask {
|
|
public:
|
|
DaemonTaskForTest(const Settings& setttings, Config* config)
|
|
: DaemonTask(Settings(), config) {}
|
|
virtual ~DaemonTaskForTest() {}
|
|
|
|
bool quit_result() { return quit_result_; }
|
|
|
|
void RunMessageLoop() { dispatcher_->DispatchForever(); }
|
|
|
|
bool Quit(const base::Closure& completion_callback) override {
|
|
quit_result_ = DaemonTask::Quit(completion_callback);
|
|
dispatcher_->PostTask(base::MessageLoop::QuitWhenIdleClosure());
|
|
return quit_result_;
|
|
}
|
|
|
|
private:
|
|
bool quit_result_;
|
|
};
|
|
|
|
class DaemonTaskTest : public Test {
|
|
public:
|
|
DaemonTaskTest()
|
|
: daemon_(DaemonTask::Settings(), &config_),
|
|
dispatcher_(new EventDispatcherForTest()),
|
|
control_(new MockControl()),
|
|
metrics_(new MockMetrics(dispatcher_)),
|
|
manager_(new MockManager(control_, dispatcher_, metrics_)),
|
|
#if !defined(DISABLE_WIFI)
|
|
callback_metrics_(new Callback80211Metrics(metrics_)),
|
|
#endif // DISABLE_WIFI
|
|
device_info_(control_, dispatcher_, metrics_, manager_) {
|
|
}
|
|
virtual ~DaemonTaskTest() {}
|
|
virtual void SetUp() {
|
|
// Tests initialization done by the daemon's constructor
|
|
daemon_.rtnl_handler_ = &rtnl_handler_;
|
|
daemon_.routing_table_ = &routing_table_;
|
|
daemon_.dhcp_provider_ = &dhcp_provider_;
|
|
daemon_.process_manager_ = &process_manager_;
|
|
daemon_.metrics_.reset(metrics_); // Passes ownership
|
|
daemon_.manager_.reset(manager_); // Passes ownership
|
|
daemon_.control_.reset(control_); // Passes ownership
|
|
daemon_.dispatcher_.reset(dispatcher_); // Passes ownership
|
|
|
|
#if !defined(DISABLE_WIFI)
|
|
daemon_.netlink_manager_ = &netlink_manager_;
|
|
// Passes ownership
|
|
daemon_.callback80211_metrics_.reset(callback_metrics_);
|
|
#endif // DISABLE_WIFI
|
|
}
|
|
void StartDaemon() { daemon_.Start(); }
|
|
|
|
void StopDaemon() { daemon_.Stop(); }
|
|
|
|
void RunDaemon() { daemon_.RunMessageLoop(); }
|
|
|
|
void ApplySettings(const DaemonTask::Settings& settings) {
|
|
daemon_.settings_ = settings;
|
|
daemon_.ApplySettings();
|
|
}
|
|
|
|
MOCK_METHOD0(TerminationAction, void());
|
|
MOCK_METHOD0(BreakTerminationLoop, void());
|
|
|
|
protected:
|
|
TestConfig config_;
|
|
DaemonTaskForTest daemon_;
|
|
MockRTNLHandler rtnl_handler_;
|
|
MockRoutingTable routing_table_;
|
|
MockDHCPProvider dhcp_provider_;
|
|
MockProcessManager process_manager_;
|
|
EventDispatcherForTest* dispatcher_;
|
|
MockControl* control_;
|
|
MockMetrics* metrics_;
|
|
MockManager* manager_;
|
|
#if !defined(DISABLE_WIFI)
|
|
MockNetlinkManager netlink_manager_;
|
|
Callback80211Metrics* callback_metrics_;
|
|
#endif // DISABLE_WIFI
|
|
DeviceInfo device_info_;
|
|
};
|
|
|
|
TEST_F(DaemonTaskTest, StartStop) {
|
|
// To ensure we do not have any stale routes, we flush a device's routes
|
|
// when it is started. This requires that the routing table is fully
|
|
// populated before we create and start devices. So test to make sure that
|
|
// the RoutingTable starts before the Manager (which in turn starts
|
|
// DeviceInfo who is responsible for creating and starting devices).
|
|
// The result is that we request the dump of the routing table and when that
|
|
// completes, we request the dump of the links. For each link found, we
|
|
// create and start the device.
|
|
EXPECT_CALL(*metrics_, Start());
|
|
EXPECT_CALL(rtnl_handler_, Start(RTMGRP_LINK | RTMGRP_IPV4_IFADDR |
|
|
RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_IFADDR |
|
|
RTMGRP_IPV6_ROUTE | RTMGRP_ND_USEROPT));
|
|
Expectation routing_table_started = EXPECT_CALL(routing_table_, Start());
|
|
EXPECT_CALL(dhcp_provider_, Init(_, _, _));
|
|
EXPECT_CALL(process_manager_, Init(_));
|
|
#if !defined(DISABLE_WIFI)
|
|
EXPECT_CALL(netlink_manager_, Init());
|
|
const uint16_t kNl80211MessageType = 42; // Arbitrary.
|
|
EXPECT_CALL(netlink_manager_,
|
|
GetFamily(Nl80211Message::kMessageTypeString, _))
|
|
.WillOnce(Return(kNl80211MessageType));
|
|
EXPECT_CALL(netlink_manager_, Start());
|
|
#endif // DISABLE_WIFI
|
|
EXPECT_CALL(*manager_, Start()).After(routing_table_started);
|
|
StartDaemon();
|
|
Mock::VerifyAndClearExpectations(metrics_);
|
|
Mock::VerifyAndClearExpectations(manager_);
|
|
|
|
EXPECT_CALL(*manager_, Stop());
|
|
EXPECT_CALL(*metrics_, Stop());
|
|
EXPECT_CALL(process_manager_, Stop());
|
|
StopDaemon();
|
|
}
|
|
|
|
ACTION_P2(CompleteAction, manager, name) {
|
|
manager->TerminationActionComplete(name);
|
|
}
|
|
|
|
TEST_F(DaemonTaskTest, QuitWithTerminationAction) {
|
|
// This expectation verifies that the termination actions are invoked.
|
|
EXPECT_CALL(*this, TerminationAction())
|
|
.WillOnce(CompleteAction(manager_, "daemon test"));
|
|
EXPECT_CALL(*this, BreakTerminationLoop()).Times(1);
|
|
|
|
manager_->AddTerminationAction(
|
|
"daemon test",
|
|
Bind(&DaemonTaskTest::TerminationAction, Unretained(this)));
|
|
|
|
// Run Daemon::Quit() after the daemon starts running.
|
|
dispatcher_->PostTask(
|
|
Bind(IgnoreResult(&DaemonTask::Quit), Unretained(&daemon_),
|
|
Bind(&DaemonTaskTest::BreakTerminationLoop, Unretained(this))));
|
|
|
|
RunDaemon();
|
|
EXPECT_FALSE(daemon_.quit_result());
|
|
}
|
|
|
|
TEST_F(DaemonTaskTest, QuitWithoutTerminationActions) {
|
|
EXPECT_CALL(*this, BreakTerminationLoop()).Times(0);
|
|
EXPECT_TRUE(daemon_.Quit(
|
|
Bind(&DaemonTaskTest::BreakTerminationLoop, Unretained(this))));
|
|
}
|
|
|
|
TEST_F(DaemonTaskTest, ApplySettings) {
|
|
DaemonTask::Settings settings;
|
|
vector<string> kEmptyStringList;
|
|
EXPECT_CALL(*manager_, SetBlacklistedDevices(kEmptyStringList));
|
|
EXPECT_CALL(*manager_, SetDHCPv6EnabledDevices(kEmptyStringList));
|
|
EXPECT_CALL(*manager_, SetTechnologyOrder("", _));
|
|
EXPECT_CALL(*manager_, SetIgnoreUnknownEthernet(false));
|
|
EXPECT_CALL(*manager_, SetStartupPortalList(_)).Times(0);
|
|
EXPECT_CALL(*manager_, SetPassiveMode()).Times(0);
|
|
EXPECT_CALL(*manager_, SetPrependDNSServers(""));
|
|
EXPECT_CALL(*manager_, SetMinimumMTU(_)).Times(0);
|
|
EXPECT_CALL(*manager_, SetAcceptHostnameFrom(""));
|
|
ApplySettings(settings);
|
|
Mock::VerifyAndClearExpectations(manager_);
|
|
|
|
vector<string> kBlacklistedDevices = {"eth0", "eth1"};
|
|
settings.device_blacklist = kBlacklistedDevices;
|
|
settings.default_technology_order = "wifi,ethernet";
|
|
vector<string> kDHCPv6EnabledDevices{"eth2", "eth3"};
|
|
settings.dhcpv6_enabled_devices = kDHCPv6EnabledDevices;
|
|
settings.ignore_unknown_ethernet = false;
|
|
settings.portal_list = "wimax";
|
|
settings.use_portal_list = true;
|
|
settings.passive_mode = true;
|
|
settings.prepend_dns_servers = "8.8.8.8,8.8.4.4";
|
|
settings.minimum_mtu = 256;
|
|
settings.accept_hostname_from = "eth*";
|
|
EXPECT_CALL(*manager_, SetBlacklistedDevices(kBlacklistedDevices));
|
|
EXPECT_CALL(*manager_, SetDHCPv6EnabledDevices(kDHCPv6EnabledDevices));
|
|
EXPECT_CALL(*manager_, SetTechnologyOrder("wifi,ethernet", _));
|
|
EXPECT_CALL(*manager_, SetIgnoreUnknownEthernet(false));
|
|
EXPECT_CALL(*manager_, SetStartupPortalList("wimax"));
|
|
EXPECT_CALL(*manager_, SetPassiveMode());
|
|
EXPECT_CALL(*manager_, SetPrependDNSServers("8.8.8.8,8.8.4.4"));
|
|
EXPECT_CALL(*manager_, SetMinimumMTU(256));
|
|
EXPECT_CALL(*manager_, SetAcceptHostnameFrom("eth*"));
|
|
ApplySettings(settings);
|
|
Mock::VerifyAndClearExpectations(manager_);
|
|
}
|
|
|
|
} // namespace shill
|