| // |
| // 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 |