blob: 9eef99f65792f04e4ec463dbb8fc7ab64b95a366 [file] [log] [blame]
// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shill/wifi_provider.h"
#include <map>
#include <set>
#include <string>
#include <vector>
#include <base/format_macros.h>
#include <base/string_number_conversions.h>
#include <base/string_util.h>
#include <base/stringprintf.h>
#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>
#include "shill/ieee80211.h"
#include "shill/mock_event_dispatcher.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_profile.h"
#include "shill/mock_store.h"
#include "shill/mock_time.h"
#include "shill/mock_wifi_service.h"
#include "shill/nice_mock_control.h"
#include "shill/technology.h"
#include "shill/wifi_endpoint.h"
#include "shill/wpa_supplicant.h"
using std::map;
using std::set;
using std::string;
using std::vector;
using ::testing::_;
using ::testing::ContainerEq;
using ::testing::Eq;
using ::testing::Invoke;
using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SetArgumentPointee;
using ::testing::StrictMock;
namespace shill {
namespace {
const time_t kFirstWeek = 50;
const char kIllegalDayProfile[] = "IllegalDay";
const time_t kSecondsPerWeek = 60 * 60 * 24 * 7;
const time_t kTestDays = 20;
} // namespace
class WiFiProviderTest : public testing::Test {
public:
WiFiProviderTest()
: metrics_(NULL),
manager_(&control_, &dispatcher_, &metrics_,
reinterpret_cast<GLib *>(NULL)),
provider_(&control_, &dispatcher_, &metrics_, &manager_),
profile_(
new NiceMock<MockProfile>(&control_, &metrics_, &manager_, "")),
storage_entry_index_(0) {
provider_.time_ = &time_;
string freq_string = StringPrintf("%s%d", WiFiProvider::kStorageFrequencies,
0);
profile_frequency_data_[freq_string].push_back(
base::StringPrintf("@%" PRIu64, static_cast<uint64_t>(kFirstWeek)));
profile_frequency_data_[freq_string].push_back("5001:1");
profile_frequency_data_[freq_string].push_back("5002:2");
freq_string = StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 1);
profile_frequency_data_[freq_string].push_back(
base::StringPrintf("@%" PRIu64, static_cast<uint64_t>(kFirstWeek) + 1));
// Overlap one entry with previous block.
profile_frequency_data_[freq_string].push_back("5001:1");
profile_frequency_data_[freq_string].push_back("6001:1");
profile_frequency_data_[freq_string].push_back("6002:2");
freq_string = StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 2);
profile_frequency_data_[freq_string].push_back(
base::StringPrintf("@%" PRIu64, static_cast<uint64_t>(kFirstWeek) + 2));
profile_frequency_data_[freq_string].push_back("7001:1");
profile_frequency_data_[freq_string].push_back("7002:2");
profile_frequency_data_[kIllegalDayProfile].push_back("7001:1");
profile_frequency_data_[kIllegalDayProfile].push_back("7002:2");
}
virtual ~WiFiProviderTest() {}
virtual void SetUp() {
EXPECT_CALL(*profile_, GetConstStorage()).WillRepeatedly(Return(&storage_));
}
bool GetStringList(const std::string &/*group*/,
const std::string &key,
std::vector<std::string> *value) {
if (!value) {
return false;
}
if (ContainsKey(profile_frequency_data_, key)) {
*value = profile_frequency_data_[key];
return true;
}
return false;
}
bool GetIllegalDayStringList(const std::string &/*group*/,
const std::string &key,
std::vector<std::string> *value) {
if (!value) {
return false;
}
if (ContainsKey(profile_frequency_data_, key)) {
*value = profile_frequency_data_[kIllegalDayProfile];
return true;
}
return false;
}
protected:
typedef scoped_refptr<MockWiFiService> MockWiFiServiceRefPtr;
void CreateServicesFromProfile() {
provider_.CreateServicesFromProfile(profile_);
}
void LoadAndFixupServiceEntries(bool is_default_profile) {
provider_.LoadAndFixupServiceEntries(&storage_, is_default_profile);
}
void Save() {
provider_.Save(&storage_);
}
const vector<WiFiServiceRefPtr> GetServices() {
return provider_.services_;
}
const WiFiProvider::EndpointServiceMap &GetServiceByEndpoint() {
return provider_.service_by_endpoint_;
}
bool GetRunning() {
return provider_.running_;
}
void AddStringParameterToStorage(const string &id,
const string &key,
const string &value) {
EXPECT_CALL(storage_, GetString(id, key, _))
.WillRepeatedly(DoAll(SetArgumentPointee<2>(value),
Return(true)));
}
string AddServiceToStorage(const char *ssid,
const char *mode,
const char *security,
bool is_hidden,
bool provide_hidden) {
string id = StringToLowerASCII(base::StringPrintf("entry_%d",
storage_entry_index_));
EXPECT_CALL(storage_, GetString(id, _, _)).WillRepeatedly(Return(false));
if (ssid) {
const string ssid_string(ssid);
const string hex_ssid(
base::HexEncode(ssid_string.data(), ssid_string.size()));
AddStringParameterToStorage(id, WiFiService::kStorageSSID, hex_ssid);
}
if (mode) {
AddStringParameterToStorage(id, WiFiService::kStorageMode, mode);
}
if (security) {
AddStringParameterToStorage(id, WiFiService::kStorageSecurity, security);
}
if (provide_hidden) {
EXPECT_CALL(storage_, GetBool(id, flimflam::kWifiHiddenSsid, _))
.WillRepeatedly(
DoAll(SetArgumentPointee<2>(is_hidden), Return(true)));
} else {
EXPECT_CALL(storage_, GetBool(id, flimflam::kWifiHiddenSsid, _))
.WillRepeatedly(Return(false));
}
storage_entry_index_++;
return id;
}
void SetServiceParameters(const char *ssid,
const char *mode,
const char *security,
bool is_hidden,
bool provide_hidden,
KeyValueStore *args) {
args->SetString(flimflam::kTypeProperty, flimflam::kTypeWifi);
if (ssid) {
args->SetString(flimflam::kSSIDProperty, ssid);
}
if (mode) {
args->SetString(flimflam::kModeProperty, mode);
}
if (security) {
args->SetString(flimflam::kSecurityProperty, security);
}
if (provide_hidden) {
args->SetBool(flimflam::kWifiHiddenSsid, is_hidden);
}
}
ServiceRefPtr CreateTemporaryService(const char *ssid,
const char *mode,
const char *security,
bool is_hidden,
bool provide_hidden,
Error *error) {
KeyValueStore args;
SetServiceParameters(
ssid, mode, security, is_hidden, provide_hidden, &args);
return provider_.CreateTemporaryService(args, error);
}
WiFiServiceRefPtr GetService(const char *ssid,
const char *mode,
const char *security,
bool is_hidden,
bool provide_hidden,
Error *error) {
KeyValueStore args;
SetServiceParameters(
ssid, mode, security, is_hidden, provide_hidden, &args);
return provider_.GetWiFiService(args, error);
}
WiFiServiceRefPtr GetWiFiService(const KeyValueStore &args, Error *error) {
return provider_.GetWiFiService(args, error);
}
WiFiServiceRefPtr FindService(const vector<uint8_t> &ssid,
const string &mode,
const string &security) {
return provider_.FindService(ssid, mode, security);
}
WiFiEndpointRefPtr MakeEndpoint(const string &ssid, const string &bssid,
uint16 frequency, int16 signal_dbm) {
return WiFiEndpoint::MakeOpenEndpoint(
NULL, NULL, ssid, bssid, WPASupplicant::kNetworkModeInfrastructure,
frequency, signal_dbm);
}
MockWiFiServiceRefPtr AddMockService(const vector<uint8_t> &ssid,
const string &mode,
const string &security,
bool hidden_ssid) {
MockWiFiServiceRefPtr service = new MockWiFiService(
&control_,
&dispatcher_,
&metrics_,
&manager_,
&provider_,
ssid,
mode,
security,
hidden_ssid);
provider_.services_.push_back(service);
return service;
}
void AddEndpointToService(WiFiServiceRefPtr service,
const WiFiEndpointConstRefPtr &endpoint) {
provider_.service_by_endpoint_[endpoint] = service;
}
void BuildFreqCountStrings(vector<string> *strings) {
// NOTE: These strings match the frequencies in |BuildFreqCountMap|. They
// are also provided, here, in sorted order to match the frequency map
// (iterators for which will provide them in frequency-sorted order).
static const char *kStrings[] = {
"@20", "5180:14", "5240:16", "5745:7", "5765:4", "5785:14", "5805:5"
};
if (!strings) {
LOG(ERROR) << "NULL |strings|.";
return;
}
for (size_t i = 0; i < arraysize(kStrings); ++i) {
(*strings).push_back(kStrings[i]);
}
}
void BuildFreqCountMap(WiFiProvider::ConnectFrequencyMap *frequencies) {
// NOTE: These structures match the strings in |BuildFreqCountStrings|.
static const struct FreqCount {
uint16 freq;
int64 count;
} kConnectFreq[] = {
{5180, 14},
{5240, 16},
{5745, 7},
{5765, 4},
{5785, 14},
{5805, 5}
};
if (!frequencies) {
LOG(ERROR) << "NULL |frequencies|.";
return;
}
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kConnectFreq); ++i) {
(*frequencies)[kConnectFreq[i].freq] = kConnectFreq[i].count;
}
}
void LoadConnectCountByFrequency(time_t today_seconds) {
provider_.time_ = &time_;
EXPECT_CALL(time_, GetSecondsSinceEpoch()).WillOnce(Return(today_seconds));
const string kGroupId =
StringPrintf("%s_0_0_%s_%s",
flimflam::kTypeWifi,
flimflam::kModeManaged,
flimflam::kSecurityNone);
EXPECT_CALL(storage_,
GetString(kGroupId, _, _)).WillRepeatedly(Return(true));
set<string> groups;
groups.insert(kGroupId);
EXPECT_CALL(storage_, GetGroups()).WillOnce(Return(groups));
// Provide data for block[0] through block[2] (block[3] is empty).
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 0), _)).
WillOnce(Invoke(this, &WiFiProviderTest::GetStringList));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 1), _)).
WillOnce(Invoke(this, &WiFiProviderTest::GetStringList));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 2), _)).
WillOnce(Invoke(this, &WiFiProviderTest::GetStringList));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 3), _)).
WillOnce(Invoke(this, &WiFiProviderTest::GetStringList));
LoadAndFixupServiceEntries(true);
}
map<string, vector<string>> profile_frequency_data_;
NiceMockControl control_;
MockEventDispatcher dispatcher_;
MockMetrics metrics_;
MockTime time_;
StrictMock<MockManager> manager_;
WiFiProvider provider_;
scoped_refptr<MockProfile> profile_;
StrictMock<MockStore> storage_;
int storage_entry_index_;
};
MATCHER(TypeWiFiPropertyMatch, "") {
return
arg.bool_properties().empty() &&
arg.int_properties().empty() &&
arg.uint_properties().empty() &&
arg.string_properties().size() == 1 &&
arg.LookupString(flimflam::kTypeProperty, "") == flimflam::kTypeWifi;
}
MATCHER_P(RefPtrMatch, ref, "") {
return ref.get() == arg.get();
}
TEST_F(WiFiProviderTest, Start) {
// Doesn't do anything really. Just testing for no crash.
EXPECT_TRUE(GetServices().empty());
EXPECT_FALSE(GetRunning());
provider_.Start();
EXPECT_TRUE(GetServices().empty());
EXPECT_TRUE(GetRunning());
EXPECT_TRUE(GetServiceByEndpoint().empty());
}
TEST_F(WiFiProviderTest, Stop) {
MockWiFiServiceRefPtr service0 = AddMockService(vector<uint8_t>(1, '0'),
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
MockWiFiServiceRefPtr service1 = AddMockService(vector<uint8_t>(1, '1'),
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
WiFiEndpointRefPtr endpoint = MakeEndpoint("", "00:00:00:00:00:00", 0, 0);
AddEndpointToService(service0, endpoint);
EXPECT_EQ(2, GetServices().size());
EXPECT_FALSE(GetServiceByEndpoint().empty());
EXPECT_CALL(*service0, ResetWiFi()).Times(1);
EXPECT_CALL(*service1, ResetWiFi()).Times(1);
EXPECT_CALL(manager_, DeregisterService(RefPtrMatch(service0))).Times(1);
EXPECT_CALL(manager_, DeregisterService(RefPtrMatch(service1))).Times(1);
provider_.Stop();
// Verify now, so it's clear that this happened as a result of the call
// above, and not anything in the destructor(s).
Mock::VerifyAndClearExpectations(service0);
Mock::VerifyAndClearExpectations(service1);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_TRUE(GetServices().empty());
EXPECT_TRUE(GetServiceByEndpoint().empty());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileWithNoGroups) {
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillOnce(Return(set<string>()));
CreateServicesFromProfile();
EXPECT_TRUE(GetServices().empty());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileMissingSSID) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
groups.insert(AddServiceToStorage(
NULL, flimflam::kModeManaged, flimflam::kSecurityNone, false, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
CreateServicesFromProfile();
EXPECT_TRUE(GetServices().empty());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileEmptySSID) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
groups.insert(AddServiceToStorage(
"", flimflam::kModeManaged, flimflam::kSecurityNone, false, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
CreateServicesFromProfile();
EXPECT_TRUE(GetServices().empty());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileMissingMode) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
groups.insert(AddServiceToStorage(
"foo", NULL, flimflam::kSecurityNone, false, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
CreateServicesFromProfile();
EXPECT_TRUE(GetServices().empty());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileEmptyMode) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
groups.insert(AddServiceToStorage(
"foo", "", flimflam::kSecurityNone, false, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
CreateServicesFromProfile();
EXPECT_TRUE(GetServices().empty());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileMissingSecurity) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
groups.insert(AddServiceToStorage(
"foo", flimflam::kModeManaged, NULL, false, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
CreateServicesFromProfile();
EXPECT_TRUE(GetServices().empty());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileEmptySecurity) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
groups.insert(AddServiceToStorage(
"foo", flimflam::kModeManaged, "", false, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
CreateServicesFromProfile();
EXPECT_TRUE(GetServices().empty());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileMissingHidden) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
groups.insert(AddServiceToStorage(
"foo", flimflam::kModeManaged, flimflam::kSecurityNone, false, false));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
CreateServicesFromProfile();
EXPECT_TRUE(GetServices().empty());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileSingle) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
string kSSID("foo");
groups.insert(AddServiceToStorage(
kSSID.c_str(), flimflam::kModeManaged, flimflam::kSecurityNone,
false, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
CreateServicesFromProfile();
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_EQ(1, GetServices().size());
const WiFiServiceRefPtr service = GetServices().front();
const string service_ssid(service->ssid().begin(), service->ssid().end());
EXPECT_EQ(kSSID, service_ssid);
EXPECT_EQ(flimflam::kModeManaged, service->mode());
EXPECT_TRUE(service->IsSecurityMatch(flimflam::kSecurityNone));
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
CreateServicesFromProfile();
EXPECT_EQ(1, GetServices().size());
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileHiddenButConnected) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
string kSSID("foo");
groups.insert(AddServiceToStorage(
kSSID.c_str(), flimflam::kModeManaged, flimflam::kSecurityNone,
true, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
EXPECT_CALL(manager_, IsTechnologyConnected(Technology::kWifi))
.WillOnce(Return(true));
EXPECT_CALL(manager_, RequestScan(_, _, _)).Times(0);
CreateServicesFromProfile();
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
EXPECT_CALL(manager_, IsTechnologyConnected(_)).Times(0);
CreateServicesFromProfile();
}
TEST_F(WiFiProviderTest, CreateServicesFromProfileHiddenNotConnected) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
string kSSID("foo");
groups.insert(AddServiceToStorage(
kSSID.c_str(), flimflam::kModeManaged, flimflam::kSecurityNone,
true, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
EXPECT_CALL(manager_, IsTechnologyConnected(Technology::kWifi))
.WillOnce(Return(false));
EXPECT_CALL(manager_, RequestScan(Device::kProgressiveScan,
flimflam::kTypeWifi, _)).Times(1);
CreateServicesFromProfile();
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
EXPECT_CALL(manager_, IsTechnologyConnected(_)).Times(0);
EXPECT_CALL(manager_, RequestScan(_, _, _)).Times(0);
CreateServicesFromProfile();
}
TEST_F(WiFiProviderTest, CreateTwoServices) {
string id;
StrictMock<MockStore> storage;
set<string> groups;
groups.insert(AddServiceToStorage(
"foo", flimflam::kModeManaged, flimflam::kSecurityNone, false, true));
groups.insert(AddServiceToStorage(
"bar", flimflam::kModeManaged, flimflam::kSecurityNone, true, true));
EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
.WillRepeatedly(Return(groups));
EXPECT_CALL(manager_, RegisterService(_)).Times(2);
EXPECT_CALL(manager_, IsTechnologyConnected(Technology::kWifi))
.WillOnce(Return(true));
EXPECT_CALL(manager_, RequestScan(_, flimflam::kTypeWifi, _)).Times(0);
CreateServicesFromProfile();
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_EQ(2, GetServices().size());
}
TEST_F(WiFiProviderTest, GetServiceEmptyMode) {
Error error;
EXPECT_FALSE(GetService("foo", "", flimflam::kSecurityNone,
false, false, &error).get());
EXPECT_EQ(Error::kNotSupported, error.type());
}
TEST_F(WiFiProviderTest, GetServiceNoMode) {
Error error;
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
EXPECT_TRUE(GetService("foo", NULL, flimflam::kSecurityNone,
false, false, &error).get());
EXPECT_TRUE(error.IsSuccess());
}
TEST_F(WiFiProviderTest, GetServiceBadMode) {
Error error;
EXPECT_FALSE(GetService("foo", "BogoMesh",
flimflam::kSecurityNone,
false, false, &error).get());
EXPECT_EQ(Error::kNotSupported, error.type());
EXPECT_EQ("service mode is unsupported", error.message());
}
TEST_F(WiFiProviderTest, GetServiceNoSSID) {
Error error;
EXPECT_FALSE(GetService(NULL, flimflam::kModeManaged,
flimflam::kSecurityNone, false, false,
&error).get());
EXPECT_EQ(Error::kInvalidArguments, error.type());
EXPECT_EQ("must specify SSID", error.message());
}
TEST_F(WiFiProviderTest, GetServiceEmptySSID) {
Error error;
EXPECT_FALSE(GetService("", flimflam::kModeManaged,
flimflam::kSecurityNone, false, false,
&error).get());
EXPECT_EQ(Error::kInvalidNetworkName, error.type());
EXPECT_EQ("SSID is too short", error.message());
}
TEST_F(WiFiProviderTest, GetServiceLongSSID) {
Error error;
string ssid(IEEE_80211::kMaxSSIDLen + 1, '0');
EXPECT_FALSE(GetService(ssid.c_str(), flimflam::kModeManaged,
flimflam::kSecurityNone, false, false,
&error).get());
EXPECT_EQ(Error::kInvalidNetworkName, error.type());
EXPECT_EQ("SSID is too long", error.message());
}
TEST_F(WiFiProviderTest, GetServiceJustLongEnoughSSID) {
Error error;
string ssid(IEEE_80211::kMaxSSIDLen, '0');
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
EXPECT_TRUE(GetService(ssid.c_str(), flimflam::kModeManaged,
flimflam::kSecurityNone, false, false,
&error));
EXPECT_TRUE(error.IsSuccess());
}
TEST_F(WiFiProviderTest, GetServiceBadSecurty) {
Error error;
EXPECT_FALSE(GetService("foo", flimflam::kModeManaged,
"pig-80211", false, false,
&error));
EXPECT_EQ(Error::kNotSupported, error.type());
EXPECT_EQ("security mode is unsupported", error.message());
}
TEST_F(WiFiProviderTest, GetServiceMinimal) {
Error error;
const string kSSID("foo");
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
WiFiServiceRefPtr service = GetService(kSSID.c_str(), flimflam::kModeManaged,
NULL, false, false, &error);
EXPECT_TRUE(service.get());
EXPECT_TRUE(error.IsSuccess());
const string service_ssid(service->ssid().begin(), service->ssid().end());
EXPECT_EQ(kSSID, service_ssid);
EXPECT_EQ(flimflam::kModeManaged, service->mode());
// These two should be set to their default values if not specified.
EXPECT_TRUE(service->IsSecurityMatch(flimflam::kSecurityNone));
EXPECT_TRUE(service->hidden_ssid());
}
TEST_F(WiFiProviderTest, GetServiceFullySpecified) {
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
const string kSSID("bar");
Error error;
WiFiServiceRefPtr service0 =
GetService(kSSID.c_str(), flimflam::kModeManaged,
flimflam::kSecurityPsk, false, true, &error);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_TRUE(error.IsSuccess());
const string service_ssid(service0->ssid().begin(), service0->ssid().end());
EXPECT_EQ(kSSID, service_ssid);
EXPECT_EQ(flimflam::kModeManaged, service0->mode());
EXPECT_TRUE(service0->IsSecurityMatch(flimflam::kSecurityPsk));
EXPECT_FALSE(service0->hidden_ssid());
// Getting the same service parameters (even with a different hidden
// parameter) should return the same service.
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
WiFiServiceRefPtr service1 =
GetService(kSSID.c_str(), flimflam::kModeManaged,
flimflam::kSecurityPsk, true, true, &error);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_EQ(service0.get(), service1.get());
EXPECT_EQ(1, GetServices().size());
// Getting the same ssid with different other parameters should return
// a different service.
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
WiFiServiceRefPtr service2 =
GetService(kSSID.c_str(), flimflam::kModeManaged,
flimflam::kSecurityNone, true, true, &error);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_NE(service0.get(), service2.get());
EXPECT_EQ(2, GetServices().size());
}
TEST_F(WiFiProviderTest, FindSimilarService) {
// Since CreateTemporyService uses exactly the same validation as
// GetService, don't bother with testing invalid parameters.
const string kSSID("foo");
KeyValueStore args;
SetServiceParameters(
kSSID.c_str(), flimflam::kModeManaged, flimflam::kSecurityNone,
true, true, &args);
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
Error get_service_error;
WiFiServiceRefPtr service = GetWiFiService(args, &get_service_error);
EXPECT_EQ(1, GetServices().size());
{
Error error;
ServiceRefPtr find_service = provider_.FindSimilarService(args, &error);
EXPECT_EQ(service.get(), find_service.get());
EXPECT_TRUE(error.IsSuccess());
}
args.SetBool(flimflam::kWifiHiddenSsid, false);
{
Error error;
ServiceRefPtr find_service = provider_.FindSimilarService(args, &error);
EXPECT_EQ(service.get(), find_service.get());
EXPECT_TRUE(error.IsSuccess());
}
args.SetString(flimflam::kSecurityProperty, flimflam::kSecurityWpa);
{
Error error;
ServiceRefPtr find_service = provider_.FindSimilarService(args, &error);
EXPECT_EQ(NULL, find_service.get());
EXPECT_EQ(Error::kNotFound, error.type());
}
}
TEST_F(WiFiProviderTest, CreateTemporaryService) {
// Since CreateTemporyService uses exactly the same validation as
// GetService, don't bother with testing invalid parameters.
const string kSSID("foo");
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
Error error;
WiFiServiceRefPtr service0 =
GetService(kSSID.c_str(), flimflam::kModeManaged,
flimflam::kSecurityNone, true, true, &error);
EXPECT_EQ(1, GetServices().size());
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
ServiceRefPtr service1 =
CreateTemporaryService(kSSID.c_str(), flimflam::kModeManaged,
flimflam::kSecurityNone, true, true, &error);
// Test that a new service was created, but not registered with the
// manager or added to the provider's service list.
EXPECT_EQ(1, GetServices().size());
EXPECT_TRUE(service0 != service1);
EXPECT_TRUE(service1->HasOneRef());
}
TEST_F(WiFiProviderTest, FindServiceWPA) {
const string kSSID("an_ssid");
Error error;
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
WiFiServiceRefPtr service = GetService(
kSSID.c_str(), flimflam::kModeManaged, flimflam::kSecurityRsn,
false, true, &error);
ASSERT_TRUE(service);
const vector<uint8_t> ssid_bytes(kSSID.begin(), kSSID.end());
WiFiServiceRefPtr wpa_service(FindService(ssid_bytes, flimflam::kModeManaged,
flimflam::kSecurityWpa));
EXPECT_TRUE(wpa_service);
EXPECT_EQ(service.get(), wpa_service.get());
WiFiServiceRefPtr rsn_service(FindService(ssid_bytes, flimflam::kModeManaged,
flimflam::kSecurityRsn));
EXPECT_TRUE(rsn_service.get());
EXPECT_EQ(service.get(), rsn_service.get());
WiFiServiceRefPtr psk_service(FindService(ssid_bytes, flimflam::kModeManaged,
flimflam::kSecurityPsk));
EXPECT_EQ(service.get(), psk_service.get());
WiFiServiceRefPtr wep_service(FindService(ssid_bytes, flimflam::kModeManaged,
flimflam::kSecurityWep));
EXPECT_TRUE(service.get() != wep_service.get());
EXPECT_EQ(NULL, wep_service.get());
}
TEST_F(WiFiProviderTest, FindServiceForEndpoint) {
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
Error error;
const string kSSID("an_ssid");
WiFiServiceRefPtr service = GetService(
kSSID.c_str(), flimflam::kModeManaged, flimflam::kSecurityNone,
false, true, &error);
ASSERT_TRUE(service);
WiFiEndpointRefPtr endpoint = MakeEndpoint(kSSID, "00:00:00:00:00:00", 0, 0);
WiFiServiceRefPtr endpoint_service =
provider_.FindServiceForEndpoint(endpoint);
// Just because a matching service exists, we shouldn't necessarily have
// it returned. We will test that this function returns the correct
// service if the endpoint is added below.
EXPECT_EQ(NULL, endpoint_service.get());
}
TEST_F(WiFiProviderTest, OnEndpointAdded) {
provider_.Start();
const string ssid0("an_ssid");
const vector<uint8_t> ssid0_bytes(ssid0.begin(), ssid0.end());
EXPECT_FALSE(FindService(ssid0_bytes, flimflam::kModeManaged,
flimflam::kSecurityNone));
WiFiEndpointRefPtr endpoint0 = MakeEndpoint(ssid0, "00:00:00:00:00:00", 0, 0);
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
EXPECT_CALL(manager_, UpdateService(_)).Times(1);
provider_.OnEndpointAdded(endpoint0);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_EQ(1, GetServices().size());
WiFiServiceRefPtr service0(FindService(ssid0_bytes, flimflam::kModeManaged,
flimflam::kSecurityNone));
EXPECT_TRUE(service0);
EXPECT_TRUE(service0->HasEndpoints());
EXPECT_EQ(1, GetServiceByEndpoint().size());
WiFiServiceRefPtr endpoint_service =
provider_.FindServiceForEndpoint(endpoint0);
EXPECT_EQ(service0.get(), endpoint_service.get());
WiFiEndpointRefPtr endpoint1 = MakeEndpoint(ssid0, "00:00:00:00:00:01", 0, 0);
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
EXPECT_CALL(manager_, UpdateService(RefPtrMatch(service0))).Times(1);
provider_.OnEndpointAdded(endpoint1);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_EQ(1, GetServices().size());
const string ssid1("another_ssid");
const vector<uint8_t> ssid1_bytes(ssid1.begin(), ssid1.end());
EXPECT_FALSE(FindService(ssid1_bytes, flimflam::kModeManaged,
flimflam::kSecurityNone));
WiFiEndpointRefPtr endpoint2 = MakeEndpoint(ssid1, "00:00:00:00:00:02",
0, 0);
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
EXPECT_CALL(manager_, UpdateService(_)).Times(1);
provider_.OnEndpointAdded(endpoint2);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_EQ(2, GetServices().size());
WiFiServiceRefPtr service1(FindService(ssid1_bytes, flimflam::kModeManaged,
flimflam::kSecurityNone));
EXPECT_TRUE(service1);
EXPECT_TRUE(service1->HasEndpoints());
EXPECT_TRUE(service1 != service0);
}
TEST_F(WiFiProviderTest, OnEndpointAddedWithSecurity) {
provider_.Start();
const string ssid0("an_ssid");
const vector<uint8_t> ssid0_bytes(ssid0.begin(), ssid0.end());
EXPECT_FALSE(FindService(ssid0_bytes, flimflam::kModeManaged,
flimflam::kSecurityNone));
WiFiEndpointRefPtr endpoint0 = MakeEndpoint(ssid0, "00:00:00:00:00:00", 0, 0);
endpoint0->set_security_mode(flimflam::kSecurityRsn);
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
EXPECT_CALL(manager_, UpdateService(_)).Times(1);
provider_.OnEndpointAdded(endpoint0);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_EQ(1, GetServices().size());
WiFiServiceRefPtr service0(FindService(ssid0_bytes, flimflam::kModeManaged,
flimflam::kSecurityWpa));
EXPECT_TRUE(service0);
EXPECT_TRUE(service0->HasEndpoints());
EXPECT_EQ(flimflam::kSecurityPsk, service0->security_);
WiFiEndpointRefPtr endpoint1 = MakeEndpoint(ssid0, "00:00:00:00:00:01", 0, 0);
endpoint1->set_security_mode(flimflam::kSecurityWpa);
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
EXPECT_CALL(manager_, UpdateService(RefPtrMatch(service0))).Times(1);
provider_.OnEndpointAdded(endpoint1);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_EQ(1, GetServices().size());
const string ssid1("another_ssid");
const vector<uint8_t> ssid1_bytes(ssid1.begin(), ssid1.end());
EXPECT_FALSE(FindService(ssid1_bytes, flimflam::kModeManaged,
flimflam::kSecurityNone));
WiFiEndpointRefPtr endpoint2 = MakeEndpoint(ssid1, "00:00:00:00:00:02", 0, 0);
endpoint2->set_security_mode(flimflam::kSecurityWpa);
EXPECT_CALL(manager_, RegisterService(_)).Times(1);
EXPECT_CALL(manager_, UpdateService(_)).Times(1);
provider_.OnEndpointAdded(endpoint2);
Mock::VerifyAndClearExpectations(&manager_);
EXPECT_EQ(2, GetServices().size());
WiFiServiceRefPtr service1(FindService(ssid1_bytes, flimflam::kModeManaged,
flimflam::kSecurityRsn));
EXPECT_TRUE(service1);
EXPECT_TRUE(service1->HasEndpoints());
EXPECT_EQ(flimflam::kSecurityPsk, service1->security_);
EXPECT_TRUE(service1 != service0);
}
TEST_F(WiFiProviderTest, OnEndpointAddedWhileStopped) {
// If we don't call provider_.Start(), OnEndpointAdded should have no effect.
const string ssid("an_ssid");
WiFiEndpointRefPtr endpoint = MakeEndpoint(ssid, "00:00:00:00:00:00", 0, 0);
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
EXPECT_CALL(manager_, UpdateService(_)).Times(0);
provider_.OnEndpointAdded(endpoint);
EXPECT_TRUE(GetServices().empty());
}
TEST_F(WiFiProviderTest, OnEndpointAddedToMockService) {
// The previous test allowed the provider to create its own "real"
// WiFiServices, which hides some of what we can test with mock
// services. Re-do an add-endpoint operation by seeding the provider
// with a mock service.
provider_.Start();
const string ssid0("an_ssid");
const vector<uint8_t> ssid0_bytes(ssid0.begin(), ssid0.end());
MockWiFiServiceRefPtr service0 = AddMockService(ssid0_bytes,
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
const string ssid1("another_ssid");
const vector<uint8_t> ssid1_bytes(ssid1.begin(), ssid1.end());
MockWiFiServiceRefPtr service1 = AddMockService(ssid1_bytes,
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
EXPECT_EQ(service0.get(), FindService(ssid0_bytes,
flimflam::kModeManaged,
flimflam::kSecurityNone).get());
WiFiEndpointRefPtr endpoint0 = MakeEndpoint(ssid0, "00:00:00:00:00:00", 0, 0);
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
EXPECT_CALL(manager_, UpdateService(RefPtrMatch(service0))).Times(1);
EXPECT_CALL(*service0, AddEndpoint(RefPtrMatch(endpoint0))).Times(1);
EXPECT_CALL(*service1, AddEndpoint(_)).Times(0);
provider_.OnEndpointAdded(endpoint0);
Mock::VerifyAndClearExpectations(&manager_);
Mock::VerifyAndClearExpectations(service0);
Mock::VerifyAndClearExpectations(service1);
WiFiEndpointRefPtr endpoint1 = MakeEndpoint(ssid0, "00:00:00:00:00:01", 0, 0);
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
EXPECT_CALL(manager_, UpdateService(RefPtrMatch(service0))).Times(1);
EXPECT_CALL(*service0, AddEndpoint(RefPtrMatch(endpoint1))).Times(1);
EXPECT_CALL(*service1, AddEndpoint(_)).Times(0);
provider_.OnEndpointAdded(endpoint1);
Mock::VerifyAndClearExpectations(&manager_);
Mock::VerifyAndClearExpectations(service0);
Mock::VerifyAndClearExpectations(service1);
WiFiEndpointRefPtr endpoint2 = MakeEndpoint(ssid1, "00:00:00:00:00:02", 0, 0);
EXPECT_CALL(manager_, RegisterService(_)).Times(0);
EXPECT_CALL(manager_, UpdateService(RefPtrMatch(service1))).Times(1);
EXPECT_CALL(*service0, AddEndpoint(_)).Times(0);
EXPECT_CALL(*service1, AddEndpoint(RefPtrMatch(endpoint2))).Times(1);
provider_.OnEndpointAdded(endpoint2);
}
TEST_F(WiFiProviderTest, OnEndpointRemoved) {
provider_.Start();
const string ssid0("an_ssid");
const vector<uint8_t> ssid0_bytes(ssid0.begin(), ssid0.end());
MockWiFiServiceRefPtr service0 = AddMockService(ssid0_bytes,
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
const string ssid1("another_ssid");
const vector<uint8_t> ssid1_bytes(ssid1.begin(), ssid1.end());
MockWiFiServiceRefPtr service1 = AddMockService(ssid1_bytes,
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
EXPECT_EQ(2, GetServices().size());
// Remove the last endpoint of a non-remembered service.
WiFiEndpointRefPtr endpoint0 = MakeEndpoint(ssid0, "00:00:00:00:00:00", 0, 0);
AddEndpointToService(service0, endpoint0);
EXPECT_EQ(1, GetServiceByEndpoint().size());
EXPECT_CALL(*service0, RemoveEndpoint(RefPtrMatch(endpoint0))).Times(1);
EXPECT_CALL(*service1, RemoveEndpoint(_)).Times(0);
EXPECT_CALL(*service0, HasEndpoints()).WillOnce(Return(false));
EXPECT_CALL(*service0, IsRemembered()).WillOnce(Return(false));
EXPECT_CALL(*service0, ResetWiFi()).Times(1);
EXPECT_CALL(manager_, UpdateService(RefPtrMatch(service0))).Times(0);
EXPECT_CALL(manager_, DeregisterService(RefPtrMatch(service0))).Times(1);
provider_.OnEndpointRemoved(endpoint0);
// Verify now, so it's clear that this happened as a result of the call
// above, and not anything in the destructor(s).
Mock::VerifyAndClearExpectations(&manager_);
Mock::VerifyAndClearExpectations(service0);
Mock::VerifyAndClearExpectations(service1);
EXPECT_EQ(1, GetServices().size());
EXPECT_EQ(service1.get(), GetServices().front().get());
EXPECT_TRUE(GetServiceByEndpoint().empty());
}
TEST_F(WiFiProviderTest, OnEndpointRemovedButHasEndpoints) {
provider_.Start();
const string ssid0("an_ssid");
const vector<uint8_t> ssid0_bytes(ssid0.begin(), ssid0.end());
MockWiFiServiceRefPtr service0 = AddMockService(ssid0_bytes,
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
EXPECT_EQ(1, GetServices().size());
// Remove an endpoint of a non-remembered service.
WiFiEndpointRefPtr endpoint0 = MakeEndpoint(ssid0, "00:00:00:00:00:00", 0, 0);
AddEndpointToService(service0, endpoint0);
EXPECT_EQ(1, GetServiceByEndpoint().size());
EXPECT_CALL(*service0, RemoveEndpoint(RefPtrMatch(endpoint0))).Times(1);
EXPECT_CALL(*service0, HasEndpoints()).WillOnce(Return(true));
EXPECT_CALL(*service0, IsRemembered()).WillRepeatedly(Return(false));
EXPECT_CALL(manager_, UpdateService(RefPtrMatch(service0))).Times(1);
EXPECT_CALL(*service0, ResetWiFi()).Times(0);
EXPECT_CALL(manager_, DeregisterService(_)).Times(0);
provider_.OnEndpointRemoved(endpoint0);
// Verify now, so it's clear that this happened as a result of the call
// above, and not anything in the destructor(s).
Mock::VerifyAndClearExpectations(&manager_);
Mock::VerifyAndClearExpectations(service0);
EXPECT_EQ(1, GetServices().size());
EXPECT_TRUE(GetServiceByEndpoint().empty());
}
TEST_F(WiFiProviderTest, OnEndpointRemovedButIsRemembered) {
provider_.Start();
const string ssid0("an_ssid");
const vector<uint8_t> ssid0_bytes(ssid0.begin(), ssid0.end());
MockWiFiServiceRefPtr service0 = AddMockService(ssid0_bytes,
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
EXPECT_EQ(1, GetServices().size());
// Remove the last endpoint of a remembered service.
WiFiEndpointRefPtr endpoint0 = MakeEndpoint(ssid0, "00:00:00:00:00:00", 0, 0);
AddEndpointToService(service0, endpoint0);
EXPECT_EQ(1, GetServiceByEndpoint().size());
EXPECT_CALL(*service0, RemoveEndpoint(RefPtrMatch(endpoint0))).Times(1);
EXPECT_CALL(*service0, HasEndpoints()).WillRepeatedly(Return(false));
EXPECT_CALL(*service0, IsRemembered()).WillOnce(Return(true));
EXPECT_CALL(manager_, UpdateService(RefPtrMatch(service0))).Times(1);
EXPECT_CALL(*service0, ResetWiFi()).Times(0);
EXPECT_CALL(manager_, DeregisterService(_)).Times(0);
provider_.OnEndpointRemoved(endpoint0);
// Verify now, so it's clear that this happened as a result of the call
// above, and not anything in the destructor(s).
Mock::VerifyAndClearExpectations(&manager_);
Mock::VerifyAndClearExpectations(service0);
EXPECT_EQ(1, GetServices().size());
EXPECT_TRUE(GetServiceByEndpoint().empty());
}
TEST_F(WiFiProviderTest, OnEndpointRemovedWhileStopped) {
// If we don't call provider_.Start(), OnEndpointRemoved should not
// cause a crash even if a service matching the endpoint does not exist.
const string ssid("an_ssid");
WiFiEndpointRefPtr endpoint = MakeEndpoint(ssid, "00:00:00:00:00:00", 0, 0);
provider_.OnEndpointRemoved(endpoint);
}
TEST_F(WiFiProviderTest, OnServiceUnloaded) {
// This function should never unregister services itself -- the Manager
// will automatically deregister the service if OnServiceUnloaded()
// returns true (via WiFiService::Unload()).
EXPECT_CALL(manager_, DeregisterService(_)).Times(0);
MockWiFiServiceRefPtr service = AddMockService(vector<uint8_t>(1, '0'),
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
EXPECT_EQ(1, GetServices().size());
EXPECT_CALL(*service, HasEndpoints()).WillOnce(Return(true));
EXPECT_CALL(*service, ResetWiFi()).Times(0);
EXPECT_FALSE(provider_.OnServiceUnloaded(service));
EXPECT_EQ(1, GetServices().size());
Mock::VerifyAndClearExpectations(service);
EXPECT_CALL(*service, HasEndpoints()).WillOnce(Return(false));
EXPECT_CALL(*service, ResetWiFi()).Times(1);
EXPECT_TRUE(provider_.OnServiceUnloaded(service));
// Verify now, so it's clear that this happened as a result of the call
// above, and not anything in the destructor(s).
Mock::VerifyAndClearExpectations(service);
EXPECT_TRUE(GetServices().empty());
Mock::VerifyAndClearExpectations(&manager_);
}
TEST_F(WiFiProviderTest, LoadAndFixupServiceEntries) {
// We test LoadAndFixupServiceEntries indirectly since it calls a static
// method in WiFiService.
EXPECT_CALL(metrics_, SendEnumToUMA(
"Network.Shill.Wifi.ServiceFixupEntries",
Metrics::kMetricServiceFixupDefaultProfile,
Metrics::kMetricServiceFixupMax)).Times(1);
EXPECT_CALL(storage_, Flush()).Times(1);
const string kGroupId =
StringPrintf("%s_0_0_%s_%s",
flimflam::kTypeWifi,
flimflam::kModeManaged,
flimflam::kSecurityNone);
EXPECT_CALL(storage_,
GetString(kGroupId, _, _)).WillRepeatedly(Return(false));
EXPECT_CALL(storage_,
SetString(kGroupId, _, _)).WillRepeatedly(Return(true));
set<string> groups;
groups.insert(kGroupId);
EXPECT_CALL(storage_, GetGroups()).WillRepeatedly(Return(groups));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 0), _)).
WillOnce(Return(true));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 1), _)).
WillOnce(Return(true));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 2), _)).
WillOnce(Return(true));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 3), _)).
WillOnce(Return(false));
LoadAndFixupServiceEntries(true);
Mock::VerifyAndClearExpectations(&metrics_);
EXPECT_CALL(metrics_, SendEnumToUMA(
"Network.Shill.Wifi.ServiceFixupEntries",
Metrics::kMetricServiceFixupUserProfile,
Metrics::kMetricServiceFixupMax)).Times(1);
EXPECT_CALL(storage_, Flush()).Times(1);
EXPECT_CALL(storage_, GetStringList(_, _, _)).Times(0);
LoadAndFixupServiceEntries(false);
}
TEST_F(WiFiProviderTest, LoadAndFixupServiceEntriesNothingToDo) {
EXPECT_CALL(metrics_, SendEnumToUMA(_, _, _)).Times(0);
EXPECT_CALL(storage_, Flush()).Times(0);
const string kGroupId =
StringPrintf("%s_0_0_%s_%s",
flimflam::kTypeWifi,
flimflam::kModeManaged,
flimflam::kSecurityNone);
EXPECT_CALL(storage_,
GetString(kGroupId, _, _)).WillRepeatedly(Return(true));
set<string> groups;
groups.insert(kGroupId);
EXPECT_CALL(storage_, GetGroups()).WillOnce(Return(groups));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 0), _)).
WillOnce(Return(true));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 1), _)).
WillOnce(Return(true));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 2), _)).
WillOnce(Return(true));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 3), _)).
WillOnce(Return(false));
LoadAndFixupServiceEntries(true);
}
TEST_F(WiFiProviderTest, GetHiddenSSIDList) {
EXPECT_TRUE(provider_.GetHiddenSSIDList().empty());
const vector<uint8_t> ssid0(1, '0');
AddMockService(ssid0, flimflam::kModeManaged,
flimflam::kSecurityNone, false);
EXPECT_TRUE(provider_.GetHiddenSSIDList().empty());
const vector<uint8_t> ssid1(1, '1');
MockWiFiServiceRefPtr service1 = AddMockService(ssid1,
flimflam::kModeManaged,
flimflam::kSecurityNone,
true);
EXPECT_CALL(*service1, IsRemembered()).WillRepeatedly(Return(false));
EXPECT_TRUE(provider_.GetHiddenSSIDList().empty());
const vector<uint8_t> ssid2(1, '2');
MockWiFiServiceRefPtr service2 = AddMockService(ssid2,
flimflam::kModeManaged,
flimflam::kSecurityNone,
true);
EXPECT_CALL(*service2, IsRemembered()).WillRepeatedly(Return(true));
ByteArrays ssid_list = provider_.GetHiddenSSIDList();
EXPECT_EQ(1, ssid_list.size());
EXPECT_TRUE(ssid_list[0] == ssid2);
const vector<uint8_t> ssid3(1, '3');
MockWiFiServiceRefPtr service3 = AddMockService(ssid3,
flimflam::kModeManaged,
flimflam::kSecurityNone,
false);
EXPECT_CALL(*service2, IsRemembered()).WillRepeatedly(Return(true));
ssid_list = provider_.GetHiddenSSIDList();
EXPECT_EQ(1, ssid_list.size());
EXPECT_TRUE(ssid_list[0] == ssid2);
const vector<uint8_t> ssid4(1, '4');
MockWiFiServiceRefPtr service4 = AddMockService(ssid4,
flimflam::kModeManaged,
flimflam::kSecurityNone,
true);
EXPECT_CALL(*service4, IsRemembered()).WillRepeatedly(Return(true));
ssid_list = provider_.GetHiddenSSIDList();
EXPECT_EQ(2, ssid_list.size());
EXPECT_TRUE(ssid_list[0] == ssid2);
EXPECT_TRUE(ssid_list[1] == ssid4);
}
TEST_F(WiFiProviderTest, StringListToFrequencyMap) {
vector<string> strings;
BuildFreqCountStrings(&strings);
WiFiProvider::ConnectFrequencyMap frequencies_result;
time_t days = WiFiProvider::StringListToFrequencyMap(strings,
&frequencies_result);
WiFiProvider::ConnectFrequencyMap frequencies_expect;
BuildFreqCountMap(&frequencies_expect);
EXPECT_THAT(frequencies_result, ContainerEq(frequencies_expect));
EXPECT_EQ(days, kTestDays);
}
TEST_F(WiFiProviderTest, StringListToFrequencyMapEmpty) {
vector<string> strings;
strings.push_back("@50");
WiFiProvider::ConnectFrequencyMap frequencies_result;
time_t days = WiFiProvider::StringListToFrequencyMap(strings,
&frequencies_result);
EXPECT_TRUE(frequencies_result.empty());
EXPECT_EQ(days, 50);
}
TEST_F(WiFiProviderTest, FrequencyMapToStringList) {
WiFiProvider::ConnectFrequencyMap frequencies;
BuildFreqCountMap(&frequencies);
vector<string> strings_result;
WiFiProvider::FrequencyMapToStringList(kTestDays, frequencies,
&strings_result);
vector<string> strings_expect;
BuildFreqCountStrings(&strings_expect);
EXPECT_THAT(strings_result, ContainerEq(strings_expect));
}
TEST_F(WiFiProviderTest, FrequencyMapToStringListEmpty) {
WiFiProvider::ConnectFrequencyMap frequencies;
vector<string> strings_result;
WiFiProvider::FrequencyMapToStringList(kTestDays, frequencies,
&strings_result);
EXPECT_EQ(1, strings_result.size());
EXPECT_EQ(*strings_result.begin(), "@20");
}
TEST_F(WiFiProviderTest, FrequencyMapBasicAging) {
const time_t kThisWeek = kFirstWeek +
WiFiProvider::kWeeksToKeepFrequencyCounts - 1;
LoadConnectCountByFrequency(kThisWeek * kSecondsPerWeek);
// Make sure we have data for all 3 blocks.
WiFiProvider::ConnectFrequencyMap expected;
expected[5001] = 2;
expected[5002] = 2;
expected[6001] = 1;
expected[6002] = 2;
expected[7001] = 1;
expected[7002] = 2;
EXPECT_THAT(provider_.connect_count_by_frequency_, ContainerEq(expected));
// And, then, make sure we output the expected blocks of data.
EXPECT_CALL(storage_, SetStringList(WiFiProvider::kStorageId, _,
Eq(profile_frequency_data_[
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 0)])));
EXPECT_CALL(storage_, SetStringList(WiFiProvider::kStorageId, _,
Eq(profile_frequency_data_[
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 1)])));
EXPECT_CALL(storage_, SetStringList(WiFiProvider::kStorageId, _,
Eq(profile_frequency_data_[
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 2)])));
vector<string> frequencies;
frequencies.push_back(base::StringPrintf("@%" PRIu64,
static_cast<uint64_t>(kThisWeek)));
EXPECT_CALL(storage_, SetStringList(WiFiProvider::kStorageId, _,
Eq(frequencies))).Times(0);
Save();
}
TEST_F(WiFiProviderTest, FrequencyMapAgingIllegalDay) {
provider_.time_ = &time_;
const time_t kThisWeek = kFirstWeek +
WiFiProvider::kWeeksToKeepFrequencyCounts - 1;
const time_t kThisWeekSeconds = kThisWeek * kSecondsPerWeek;
EXPECT_CALL(time_, GetSecondsSinceEpoch()).WillOnce(Return(kThisWeekSeconds));
const string kGroupId =
StringPrintf("%s_0_0_%s_%s",
flimflam::kTypeWifi,
flimflam::kModeManaged,
flimflam::kSecurityNone);
EXPECT_CALL(storage_,
GetString(kGroupId, _, _)).WillRepeatedly(Return(true));
set<string> groups;
groups.insert(kGroupId);
// Instead of block[1], return a block without the date.
EXPECT_CALL(storage_, GetGroups()).WillOnce(Return(groups));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 0), _)).
WillOnce(Invoke(this, &WiFiProviderTest::GetStringList));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 1), _)).
WillOnce(Invoke(this, &WiFiProviderTest::GetIllegalDayStringList));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 2), _)).
WillOnce(Invoke(this, &WiFiProviderTest::GetStringList));
EXPECT_CALL(storage_, GetStringList(WiFiProvider::kStorageId,
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 3), _)).
WillOnce(Invoke(this, &WiFiProviderTest::GetStringList));
LoadAndFixupServiceEntries(true);
// Verify that the received information only includes block[0] and block[2].
WiFiProvider::ConnectFrequencyMap expected;
expected[5001] = 1;
expected[5002] = 2;
expected[7001] = 1;
expected[7002] = 2;
EXPECT_THAT(provider_.connect_count_by_frequency_, ContainerEq(expected));
// And, then, make sure we output the expected blocks of data.
EXPECT_CALL(storage_, SetStringList(WiFiProvider::kStorageId, _,
Eq(profile_frequency_data_[
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 0)])));
EXPECT_CALL(storage_, SetStringList(WiFiProvider::kStorageId, _,
Eq(profile_frequency_data_[
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 1)]))).
Times(0);
EXPECT_CALL(storage_, SetStringList(WiFiProvider::kStorageId, _,
Eq(profile_frequency_data_[
StringPrintf("%s%d", WiFiProvider::kStorageFrequencies, 2)])));
vector<string> frequencies;
frequencies.push_back(base::StringPrintf("@%" PRIu64,
static_cast<uint64_t>(kThisWeek)));
EXPECT_CALL(storage_, SetStringList(WiFiProvider::kStorageId, _,
Eq(frequencies))).Times(0);
Save();
}
TEST_F(WiFiProviderTest, IncrementConnectCount) {
const time_t kThisWeek = kFirstWeek +
WiFiProvider::kWeeksToKeepFrequencyCounts - 1;
const time_t kThisWeekSeconds = kThisWeek * kSecondsPerWeek;
LoadConnectCountByFrequency(kThisWeekSeconds);
EXPECT_CALL(time_, GetSecondsSinceEpoch()).WillOnce(Return(kThisWeekSeconds));
EXPECT_CALL(manager_, UpdateWiFiProvider());
EXPECT_CALL(metrics_, SendToUMA(_, _, _, _, _));
time_t newest_week_at_start =
provider_.connect_count_by_frequency_dated_.crbegin()->first;
provider_.IncrementConnectCount(6002);
// Make sure we have data for all 3 blocks.
WiFiProvider::ConnectFrequencyMap expected;
expected[5001] = 2;
expected[5002] = 2;
expected[6001] = 1;
expected[6002] = 3;
expected[7001] = 1;
expected[7002] = 2;
EXPECT_THAT(provider_.connect_count_by_frequency_, ContainerEq(expected));
// Make sure we didn't delete the oldest block.
EXPECT_TRUE(ContainsKey(provider_.connect_count_by_frequency_dated_,
kFirstWeek));
// Make sure we didn't create a new block.
time_t newest_week_at_end =
provider_.connect_count_by_frequency_dated_.crbegin()->first;
EXPECT_EQ(newest_week_at_start, newest_week_at_end);
}
TEST_F(WiFiProviderTest, IncrementConnectCountCreateNew) {
time_t this_week = kFirstWeek + WiFiProvider::kWeeksToKeepFrequencyCounts - 1;
LoadConnectCountByFrequency(this_week * kSecondsPerWeek);
this_week += 2;
EXPECT_CALL(time_, GetSecondsSinceEpoch()).
WillOnce(Return(this_week * kSecondsPerWeek));
EXPECT_CALL(manager_, UpdateWiFiProvider());
EXPECT_CALL(metrics_, SendToUMA(_, _, _, _, _));
time_t newest_week_at_start =
provider_.connect_count_by_frequency_dated_.crbegin()->first;
provider_.IncrementConnectCount(6001);
// Make sure we have data for newest 2 blocks (only).
WiFiProvider::ConnectFrequencyMap expected;
expected[5001] = 1;
expected[6001] = 2;
expected[6002] = 2;
expected[7001] = 1;
expected[7002] = 2;
EXPECT_THAT(provider_.connect_count_by_frequency_, ContainerEq(expected));
// Verify that the oldest block is gone.
EXPECT_FALSE(ContainsKey(provider_.connect_count_by_frequency_dated_,
kFirstWeek));
// Make sure we created a new block and that it is for the current week.
time_t newest_week_at_end =
provider_.connect_count_by_frequency_dated_.crbegin()->first;
EXPECT_NE(newest_week_at_start, newest_week_at_end);
EXPECT_TRUE(ContainsKey(provider_.connect_count_by_frequency_dated_,
this_week));
}
} // namespace shill