363 lines
14 KiB
C++
363 lines
14 KiB
C++
//
|
|
// Copyright (C) 2014 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 "apmanager/device.h"
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <base/strings/stringprintf.h>
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
#include <shill/net/ieee80211.h>
|
|
#include <shill/net/nl80211_attribute.h>
|
|
#include <shill/net/nl80211_message.h>
|
|
|
|
#include "apmanager/fake_device_adaptor.h"
|
|
#include "apmanager/mock_control.h"
|
|
#include "apmanager/mock_manager.h"
|
|
|
|
using ::testing::_;
|
|
using ::testing::Mock;
|
|
using ::testing::ReturnNew;
|
|
using std::vector;
|
|
|
|
namespace apmanager {
|
|
|
|
namespace {
|
|
|
|
const char kDeviceName[] = "phy0";
|
|
const Device::WiFiInterface kApModeInterface0 = {
|
|
"uap0", kDeviceName, 1, NL80211_IFTYPE_AP
|
|
};
|
|
const Device::WiFiInterface kApModeInterface1 = {
|
|
"uap1", kDeviceName, 2, NL80211_IFTYPE_AP
|
|
};
|
|
const Device::WiFiInterface kManagedModeInterface0 = {
|
|
"wlan0", kDeviceName, 3, NL80211_IFTYPE_STATION
|
|
};
|
|
const Device::WiFiInterface kManagedModeInterface1 = {
|
|
"wlan1", kDeviceName, 4, NL80211_IFTYPE_STATION
|
|
};
|
|
const Device::WiFiInterface kMonitorModeInterface = {
|
|
"monitor0", kDeviceName, 5, NL80211_IFTYPE_MONITOR
|
|
};
|
|
|
|
} // namespace
|
|
|
|
class DeviceTest : public testing::Test {
|
|
public:
|
|
DeviceTest() : manager_(&control_interface_) {
|
|
ON_CALL(control_interface_, CreateDeviceAdaptorRaw())
|
|
.WillByDefault(ReturnNew<FakeDeviceAdaptor>());
|
|
device_ = new Device(&manager_, kDeviceName, 0);
|
|
}
|
|
|
|
void VerifyInterfaceList(
|
|
const vector<Device::WiFiInterface>& interface_list) {
|
|
EXPECT_EQ(interface_list.size(), device_->interface_list_.size());
|
|
for (size_t i = 0; i < interface_list.size(); i++) {
|
|
EXPECT_TRUE(interface_list[i].Equals(device_->interface_list_[i]));
|
|
}
|
|
}
|
|
|
|
void VerifyPreferredApInterface(const std::string& interface_name) {
|
|
EXPECT_EQ(interface_name, device_->GetPreferredApInterface());
|
|
}
|
|
|
|
void AddWiphyBandAttribute(shill::AttributeListRefPtr wiphy_bands,
|
|
const std::string& band_name,
|
|
int band_id,
|
|
std::vector<uint32_t> frequency_list,
|
|
uint16_t ht_cap_mask) {
|
|
// Band attribute.
|
|
shill::AttributeListRefPtr wiphy_band;
|
|
wiphy_bands->CreateNestedAttribute(band_id, band_name.c_str());
|
|
wiphy_bands->GetNestedAttributeList(band_id, &wiphy_band);
|
|
// Frequencies attribute.
|
|
shill::AttributeListRefPtr frequencies;
|
|
wiphy_band->CreateNestedAttribute(NL80211_BAND_ATTR_FREQS,
|
|
"NL80211_BAND_ATTR_FREQS");
|
|
wiphy_band->GetNestedAttributeList(NL80211_BAND_ATTR_FREQS,
|
|
&frequencies);
|
|
// Frequency attribute.
|
|
for (size_t i = 0; i < frequency_list.size(); i++) {
|
|
shill::AttributeListRefPtr frequency;
|
|
frequencies->CreateNestedAttribute(
|
|
i, base::StringPrintf("Frequency %d", frequency_list[i]).c_str());
|
|
frequencies->GetNestedAttributeList(i, &frequency);
|
|
frequency->CreateU32Attribute(NL80211_FREQUENCY_ATTR_FREQ,
|
|
"NL80211_FREQUENCY_ATTR_FREQ");
|
|
frequency->SetU32AttributeValue(NL80211_FREQUENCY_ATTR_FREQ,
|
|
frequency_list[i]);
|
|
frequencies->SetNestedAttributeHasAValue(i);
|
|
}
|
|
wiphy_band->SetNestedAttributeHasAValue(NL80211_BAND_ATTR_FREQS);
|
|
|
|
// HT Capability attribute.
|
|
wiphy_band->CreateU16Attribute(NL80211_BAND_ATTR_HT_CAPA,
|
|
"NL80211_BAND_ATTR_HT_CAPA");
|
|
wiphy_band->SetU16AttributeValue(NL80211_BAND_ATTR_HT_CAPA, ht_cap_mask);
|
|
|
|
wiphy_bands->SetNestedAttributeHasAValue(band_id);
|
|
}
|
|
|
|
void EnableApModeSupport() {
|
|
device_->supports_ap_mode_ = true;
|
|
}
|
|
|
|
void VerifyApModeSupport(bool supports_ap_mode) {
|
|
EXPECT_EQ(supports_ap_mode, device_->supports_ap_mode_);
|
|
}
|
|
|
|
void VerifyFrequencyList(int band_id, std::vector<uint32_t> frequency_list) {
|
|
EXPECT_EQ(frequency_list, device_->band_capability_[band_id].frequencies);
|
|
}
|
|
|
|
protected:
|
|
MockControl control_interface_;
|
|
MockManager manager_;
|
|
scoped_refptr<Device> device_;
|
|
};
|
|
|
|
TEST_F(DeviceTest, RegisterInterface) {
|
|
vector<Device::WiFiInterface> interface_list;
|
|
interface_list.push_back(kApModeInterface0);
|
|
interface_list.push_back(kManagedModeInterface0);
|
|
interface_list.push_back(kMonitorModeInterface);
|
|
|
|
device_->RegisterInterface(kApModeInterface0);
|
|
device_->RegisterInterface(kManagedModeInterface0);
|
|
device_->RegisterInterface(kMonitorModeInterface);
|
|
|
|
// Verify result interface list.
|
|
VerifyInterfaceList(interface_list);
|
|
}
|
|
|
|
TEST_F(DeviceTest, DeregisterInterface) {
|
|
vector<Device::WiFiInterface> interface_list;
|
|
interface_list.push_back(kApModeInterface0);
|
|
interface_list.push_back(kManagedModeInterface0);
|
|
|
|
// Register all interfaces, then deregister monitor0 and wlan1 interfaces.
|
|
device_->RegisterInterface(kApModeInterface0);
|
|
device_->RegisterInterface(kMonitorModeInterface);
|
|
device_->RegisterInterface(kManagedModeInterface0);
|
|
device_->RegisterInterface(kManagedModeInterface1);
|
|
device_->DeregisterInterface(kMonitorModeInterface);
|
|
device_->DeregisterInterface(kManagedModeInterface1);
|
|
|
|
// Verify result interface list.
|
|
VerifyInterfaceList(interface_list);
|
|
}
|
|
|
|
TEST_F(DeviceTest, PreferredAPInterface) {
|
|
EnableApModeSupport();
|
|
|
|
// Register a monitor mode interface, no preferred AP mode interface.
|
|
device_->RegisterInterface(kMonitorModeInterface);
|
|
VerifyPreferredApInterface("");
|
|
|
|
// Register a managed mode interface, should be set to preferred AP interface.
|
|
device_->RegisterInterface(kManagedModeInterface0);
|
|
VerifyPreferredApInterface(kManagedModeInterface0.iface_name);
|
|
|
|
// Register a ap mode interface, should be set to preferred AP interface.
|
|
device_->RegisterInterface(kApModeInterface0);
|
|
VerifyPreferredApInterface(kApModeInterface0.iface_name);
|
|
|
|
// Register another ap mode interface "uap1" and managed mode interface
|
|
// "wlan1", preferred AP interface should still be set to the first detected
|
|
// ap mode interface "uap0".
|
|
device_->RegisterInterface(kApModeInterface1);
|
|
device_->RegisterInterface(kManagedModeInterface1);
|
|
VerifyPreferredApInterface(kApModeInterface0.iface_name);
|
|
|
|
// Deregister the first ap mode interface, preferred AP interface should be
|
|
// set to the second ap mode interface.
|
|
device_->DeregisterInterface(kApModeInterface0);
|
|
VerifyPreferredApInterface(kApModeInterface1.iface_name);
|
|
|
|
// Deregister the second ap mode interface, preferred AP interface should be
|
|
// set the first managed mode interface.
|
|
device_->DeregisterInterface(kApModeInterface1);
|
|
VerifyPreferredApInterface(kManagedModeInterface0.iface_name);
|
|
|
|
// Deregister the first managed mode interface, preferred AP interface
|
|
// should be set to the second managed mode interface.
|
|
device_->DeregisterInterface(kManagedModeInterface0);
|
|
VerifyPreferredApInterface(kManagedModeInterface1.iface_name);
|
|
|
|
// Deregister the second managed mode interface, preferred AP interface
|
|
// should be set to empty string.
|
|
device_->DeregisterInterface(kManagedModeInterface1);
|
|
VerifyPreferredApInterface("");
|
|
}
|
|
|
|
TEST_F(DeviceTest, DeviceWithoutAPModeSupport) {
|
|
// AP mode support is not enabled for the device, so no preferred AP
|
|
// mode interface.
|
|
device_->RegisterInterface(kApModeInterface0);
|
|
VerifyPreferredApInterface("");
|
|
}
|
|
|
|
TEST_F(DeviceTest, ParseWiphyCapability) {
|
|
shill::NewWiphyMessage message;
|
|
|
|
// Supported interface types attribute.
|
|
message.attributes()->CreateNestedAttribute(
|
|
NL80211_ATTR_SUPPORTED_IFTYPES, "NL80211_ATTR_SUPPORTED_IFTYPES");
|
|
shill::AttributeListRefPtr supported_iftypes;
|
|
message.attributes()->GetNestedAttributeList(
|
|
NL80211_ATTR_SUPPORTED_IFTYPES, &supported_iftypes);
|
|
// Add support for AP mode interface.
|
|
supported_iftypes->CreateFlagAttribute(
|
|
NL80211_IFTYPE_AP, "NL80211_IFTYPE_AP");
|
|
supported_iftypes->SetFlagAttributeValue(NL80211_IFTYPE_AP, true);
|
|
message.attributes()->SetNestedAttributeHasAValue(
|
|
NL80211_ATTR_SUPPORTED_IFTYPES);
|
|
|
|
// Wiphy bands attribute.
|
|
message.attributes()->CreateNestedAttribute(
|
|
NL80211_ATTR_WIPHY_BANDS, "NL80211_ATTR_WIPHY_BANDS");
|
|
shill::AttributeListRefPtr wiphy_bands;
|
|
message.attributes()->GetNestedAttributeList(
|
|
NL80211_ATTR_WIPHY_BANDS, &wiphy_bands);
|
|
|
|
// 2.4GHz band capability.
|
|
const uint32_t kBand24GHzFrequencies[] = {
|
|
2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467};
|
|
const uint16_t kBand24GHzHTCapMask = shill::IEEE_80211::kHTCapMaskLdpcCoding |
|
|
shill::IEEE_80211::kHTCapMaskGrnFld |
|
|
shill::IEEE_80211::kHTCapMaskSgi20;
|
|
std::vector<uint32_t> band_24ghz_freq_list(
|
|
kBand24GHzFrequencies,
|
|
kBand24GHzFrequencies + sizeof(kBand24GHzFrequencies) /
|
|
sizeof(kBand24GHzFrequencies[0]));
|
|
AddWiphyBandAttribute(
|
|
wiphy_bands, "2.4GHz band", 0, band_24ghz_freq_list,
|
|
kBand24GHzHTCapMask);
|
|
|
|
// 5GHz band capability.
|
|
const uint32_t kBand5GHzFrequencies[] = {
|
|
5180, 5190, 5200, 5210, 5220, 5230, 5240, 5260, 5280, 5300, 5320};
|
|
const uint16_t kBand5GHzHTCapMask =
|
|
shill::IEEE_80211::kHTCapMaskLdpcCoding |
|
|
shill::IEEE_80211::kHTCapMaskSupWidth2040 |
|
|
shill::IEEE_80211::kHTCapMaskGrnFld |
|
|
shill::IEEE_80211::kHTCapMaskSgi20 |
|
|
shill::IEEE_80211::kHTCapMaskSgi40;
|
|
std::vector<uint32_t> band_5ghz_freq_list(
|
|
kBand5GHzFrequencies,
|
|
kBand5GHzFrequencies + sizeof(kBand5GHzFrequencies) /
|
|
sizeof(kBand5GHzFrequencies[0]));
|
|
AddWiphyBandAttribute(
|
|
wiphy_bands, "5GHz band", 1, band_5ghz_freq_list, kBand5GHzHTCapMask);
|
|
|
|
message.attributes()->SetNestedAttributeHasAValue(NL80211_ATTR_WIPHY_BANDS);
|
|
|
|
device_->ParseWiphyCapability(message);
|
|
|
|
// Verify AP mode support.
|
|
VerifyApModeSupport(true);
|
|
|
|
// Verify frequency list for both bands.
|
|
VerifyFrequencyList(0, band_24ghz_freq_list);
|
|
VerifyFrequencyList(1, band_5ghz_freq_list);
|
|
|
|
// Verify HT Capablity for 2.4GHz band.
|
|
const char kBand24GHzHTCapability[] = "[LDPC SMPS-STATIC GF SHORT-GI-20]";
|
|
std::string band_24ghz_cap;
|
|
EXPECT_TRUE(device_->GetHTCapability(6, &band_24ghz_cap));
|
|
EXPECT_EQ(kBand24GHzHTCapability, band_24ghz_cap);
|
|
|
|
// Verify HT Capablity for 5GHz band.
|
|
const char kBand5GHzHTCapability[] =
|
|
"[LDPC HT40+ SMPS-STATIC GF SHORT-GI-20 SHORT-GI-40]";
|
|
std::string band_5ghz_cap;
|
|
EXPECT_TRUE(device_->GetHTCapability(36, &band_5ghz_cap));
|
|
EXPECT_EQ(kBand5GHzHTCapability, band_5ghz_cap);
|
|
}
|
|
|
|
TEST_F(DeviceTest, ClaimAndReleaseDeviceWithFullControl) {
|
|
EnableApModeSupport();
|
|
|
|
// Register multiple interfaces.
|
|
device_->RegisterInterface(kApModeInterface1);
|
|
device_->RegisterInterface(kManagedModeInterface1);
|
|
|
|
// Claim the device should claim all interfaces registered on this device..
|
|
EXPECT_CALL(manager_, ClaimInterface(kApModeInterface1.iface_name)).Times(1);
|
|
EXPECT_CALL(manager_,
|
|
ClaimInterface(kManagedModeInterface1.iface_name)).Times(1);
|
|
EXPECT_TRUE(device_->ClaimDevice(true));
|
|
Mock::VerifyAndClearExpectations(&manager_);
|
|
|
|
// Claim the device when it is already claimed.
|
|
EXPECT_CALL(manager_, ClaimInterface(_)).Times(0);
|
|
EXPECT_FALSE(device_->ClaimDevice(true));
|
|
Mock::VerifyAndClearExpectations(&manager_);
|
|
|
|
// Release the device should release all interfaces registered on this device.
|
|
EXPECT_CALL(manager_,
|
|
ReleaseInterface(kApModeInterface1.iface_name)).Times(1);
|
|
EXPECT_CALL(manager_,
|
|
ReleaseInterface(kManagedModeInterface1.iface_name)).Times(1);
|
|
EXPECT_TRUE(device_->ReleaseDevice());
|
|
Mock::VerifyAndClearExpectations(&manager_);
|
|
|
|
// Release the device when it is not claimed.
|
|
EXPECT_CALL(manager_, ReleaseInterface(_)).Times(0);
|
|
EXPECT_FALSE(device_->ReleaseDevice());
|
|
Mock::VerifyAndClearExpectations(&manager_);
|
|
}
|
|
|
|
TEST_F(DeviceTest, ClaimAndReleaseDeviceWithoutFullControl) {
|
|
EnableApModeSupport();
|
|
|
|
// Register multiple interfaces.
|
|
device_->RegisterInterface(kApModeInterface1);
|
|
device_->RegisterInterface(kManagedModeInterface1);
|
|
|
|
// Claim the device should only claim the preferred AP interface registered
|
|
// on this device.
|
|
EXPECT_CALL(manager_, ClaimInterface(kApModeInterface1.iface_name)).Times(1);
|
|
EXPECT_CALL(manager_,
|
|
ClaimInterface(kManagedModeInterface1.iface_name)).Times(0);
|
|
EXPECT_TRUE(device_->ClaimDevice(false));
|
|
Mock::VerifyAndClearExpectations(&manager_);
|
|
|
|
// Claim the device when it is already claimed.
|
|
EXPECT_CALL(manager_, ClaimInterface(_)).Times(0);
|
|
EXPECT_FALSE(device_->ClaimDevice(false));
|
|
Mock::VerifyAndClearExpectations(&manager_);
|
|
|
|
// Release the device should release the preferred AP interface registered
|
|
// on this device.
|
|
EXPECT_CALL(manager_,
|
|
ReleaseInterface(kApModeInterface1.iface_name)).Times(1);
|
|
EXPECT_CALL(manager_,
|
|
ReleaseInterface(kManagedModeInterface1.iface_name)).Times(0);
|
|
EXPECT_TRUE(device_->ReleaseDevice());
|
|
Mock::VerifyAndClearExpectations(&manager_);
|
|
|
|
// Release the device when it is not claimed.
|
|
EXPECT_CALL(manager_, ReleaseInterface(_)).Times(0);
|
|
EXPECT_FALSE(device_->ReleaseDevice());
|
|
Mock::VerifyAndClearExpectations(&manager_);
|
|
}
|
|
|
|
} // namespace apmanager
|