diff options
Diffstat (limited to 'wifi/1.3/default/tests')
18 files changed, 2076 insertions, 0 deletions
diff --git a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp new file mode 100644 index 0000000000..dbf7bd6113 --- /dev/null +++ b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2017, 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <gmock/gmock.h> + +#undef NAN +#include "hidl_struct_util.h" + +using testing::Test; + +namespace { +constexpr uint32_t kMacId1 = 1; +constexpr uint32_t kMacId2 = 2; +constexpr uint32_t kIfaceChannel1 = 3; +constexpr uint32_t kIfaceChannel2 = 5; +constexpr char kIfaceName1[] = "wlan0"; +constexpr char kIfaceName2[] = "wlan1"; +} // namespace +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; +using ::android::hardware::wifi::V1_0::WifiChannelWidthInMhz; + +class HidlStructUtilTest : public Test {}; + +TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithOneMac) { + std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos; + legacy_hal::WifiMacInfo legacy_mac_info1 = { + .wlan_mac_id = kMacId1, + .mac_band = + legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_2_4_BAND}; + legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1, + .channel = kIfaceChannel1}; + legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2, + .channel = kIfaceChannel2}; + legacy_mac_info1.iface_infos.push_back(legacy_iface_info1); + legacy_mac_info1.iface_infos.push_back(legacy_iface_info2); + legacy_mac_infos.push_back(legacy_mac_info1); + + std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo> + hidl_radio_mode_infos; + ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl( + legacy_mac_infos, &hidl_radio_mode_infos)); + + ASSERT_EQ(1u, hidl_radio_mode_infos.size()); + auto hidl_radio_mode_info1 = hidl_radio_mode_infos[0]; + EXPECT_EQ(legacy_mac_info1.wlan_mac_id, hidl_radio_mode_info1.radioId); + EXPECT_EQ(WifiBand::BAND_24GHZ_5GHZ, hidl_radio_mode_info1.bandInfo); + ASSERT_EQ(2u, hidl_radio_mode_info1.ifaceInfos.size()); + auto hidl_iface_info1 = hidl_radio_mode_info1.ifaceInfos[0]; + EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name); + EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel), + hidl_iface_info1.channel); + auto hidl_iface_info2 = hidl_radio_mode_info1.ifaceInfos[1]; + EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name); + EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel), + hidl_iface_info2.channel); +} + +TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) { + std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos; + legacy_hal::WifiMacInfo legacy_mac_info1 = { + .wlan_mac_id = kMacId1, .mac_band = legacy_hal::WLAN_MAC_5_0_BAND}; + legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1, + .channel = kIfaceChannel1}; + legacy_hal::WifiMacInfo legacy_mac_info2 = { + .wlan_mac_id = kMacId2, .mac_band = legacy_hal::WLAN_MAC_2_4_BAND}; + legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2, + .channel = kIfaceChannel2}; + legacy_mac_info1.iface_infos.push_back(legacy_iface_info1); + legacy_mac_infos.push_back(legacy_mac_info1); + legacy_mac_info2.iface_infos.push_back(legacy_iface_info2); + legacy_mac_infos.push_back(legacy_mac_info2); + + std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo> + hidl_radio_mode_infos; + ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl( + legacy_mac_infos, &hidl_radio_mode_infos)); + + ASSERT_EQ(2u, hidl_radio_mode_infos.size()); + + // Find mac info 1. + const auto hidl_radio_mode_info1 = + std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), + [&legacy_mac_info1]( + const V1_2::IWifiChipEventCallback::RadioModeInfo& x) { + return x.radioId == legacy_mac_info1.wlan_mac_id; + }); + ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1); + EXPECT_EQ(WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo); + ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size()); + auto hidl_iface_info1 = hidl_radio_mode_info1->ifaceInfos[0]; + EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name); + EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel), + hidl_iface_info1.channel); + + // Find mac info 2. + const auto hidl_radio_mode_info2 = + std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(), + [&legacy_mac_info2]( + const V1_2::IWifiChipEventCallback::RadioModeInfo& x) { + return x.radioId == legacy_mac_info2.wlan_mac_id; + }); + ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2); + EXPECT_EQ(WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo); + ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size()); + auto hidl_iface_info2 = hidl_radio_mode_info2->ifaceInfos[0]; + EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name); + EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel), + hidl_iface_info2.channel); +} + +TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) { + legacy_hal::LinkLayerStats legacy_stats{}; + legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); + legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); + legacy_stats.iface.beacon_rx = rand(); + legacy_stats.iface.rssi_mgmt = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries = rand(); + + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries = rand(); + + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries = rand(); + + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand(); + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries = rand(); + + for (auto& radio : legacy_stats.radios) { + radio.stats.on_time = rand(); + radio.stats.tx_time = rand(); + radio.stats.rx_time = rand(); + radio.stats.on_time_scan = rand(); + radio.stats.on_time_nbd = rand(); + radio.stats.on_time_gscan = rand(); + radio.stats.on_time_roam_scan = rand(); + radio.stats.on_time_pno_scan = rand(); + radio.stats.on_time_hs20 = rand(); + for (int i = 0; i < 4; i++) { + radio.tx_time_per_levels.push_back(rand()); + } + + legacy_hal::wifi_channel_stat channel_stat1 = { + .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 2437, 2437, 0}, + .cca_busy_time = 0x55, + .on_time = 0x1111}; + legacy_hal::wifi_channel_stat channel_stat2 = { + .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 5180, 5180, 0}, + .cca_busy_time = 0x66, + .on_time = 0x2222}; + radio.channel_stats.push_back(channel_stat1); + radio.channel_stats.push_back(channel_stat2); + } + + V1_3::StaLinkLayerStats converted{}; + hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, + &converted); + EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.beaconRx); + EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu, + converted.iface.wmeBePktStats.rxMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu, + converted.iface.wmeBePktStats.txMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost, + converted.iface.wmeBePktStats.lostMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries, + converted.iface.wmeBePktStats.retries); + + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu, + converted.iface.wmeBkPktStats.rxMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu, + converted.iface.wmeBkPktStats.txMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost, + converted.iface.wmeBkPktStats.lostMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries, + converted.iface.wmeBkPktStats.retries); + + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu, + converted.iface.wmeViPktStats.rxMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu, + converted.iface.wmeViPktStats.txMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost, + converted.iface.wmeViPktStats.lostMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries, + converted.iface.wmeViPktStats.retries); + + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu, + converted.iface.wmeVoPktStats.rxMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu, + converted.iface.wmeVoPktStats.txMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost, + converted.iface.wmeVoPktStats.lostMpdu); + EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries, + converted.iface.wmeVoPktStats.retries); + + EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size()); + for (size_t i = 0; i < legacy_stats.radios.size(); i++) { + EXPECT_EQ(legacy_stats.radios[i].stats.on_time, + converted.radios[i].V1_0.onTimeInMs); + EXPECT_EQ(legacy_stats.radios[i].stats.tx_time, + converted.radios[i].V1_0.txTimeInMs); + EXPECT_EQ(legacy_stats.radios[i].stats.rx_time, + converted.radios[i].V1_0.rxTimeInMs); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan, + converted.radios[i].V1_0.onTimeInMsForScan); + EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(), + converted.radios[i].V1_0.txTimeInMsPerLevel.size()); + for (size_t j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size(); + j++) { + EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j], + converted.radios[i].V1_0.txTimeInMsPerLevel[j]); + } + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd, + converted.radios[i].onTimeInMsForNanScan); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan, + converted.radios[i].onTimeInMsForBgScan); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan, + converted.radios[i].onTimeInMsForRoamScan); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan, + converted.radios[i].onTimeInMsForPnoScan); + EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20, + converted.radios[i].onTimeInMsForHs20Scan); + EXPECT_EQ(legacy_stats.radios[i].channel_stats.size(), + converted.radios[i].channelStats.size()); + for (size_t k = 0; k < legacy_stats.radios[i].channel_stats.size(); + k++) { + auto& legacy_channel_st = legacy_stats.radios[i].channel_stats[k]; + EXPECT_EQ(WifiChannelWidthInMhz::WIDTH_20, + converted.radios[i].channelStats[k].channel.width); + EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq), + converted.radios[i].channelStats[k].channel.centerFreq); + EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq0), + converted.radios[i].channelStats[k].channel.centerFreq0); + EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq1), + converted.radios[i].channelStats[k].channel.centerFreq1); + EXPECT_EQ(legacy_channel_st.cca_busy_time, + converted.radios[i].channelStats[k].ccaBusyTimeInMs); + EXPECT_EQ(legacy_channel_st.on_time, + converted.radios[i].channelStats[k].onTimeInMs); + } + } +} + +TEST_F(HidlStructUtilTest, CanConvertLegacyFeaturesToHidl) { + using HidlChipCaps = V1_3::IWifiChip::ChipCapabilityMask; + + uint32_t hidle_caps; + + uint32_t legacy_feature_set = + WIFI_FEATURE_D2D_RTT | WIFI_FEATURE_SET_LATENCY_MODE; + uint32_t legacy_logger_feature_set = + legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED; + + ASSERT_TRUE(hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities( + legacy_feature_set, legacy_logger_feature_set, &hidle_caps)); + + EXPECT_EQ(HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA | + HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS | + HidlChipCaps::DEBUG_ERROR_ALERTS | HidlChipCaps::D2D_RTT | + HidlChipCaps::SET_LATENCY_MODE | + HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP, + hidle_caps); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/main.cpp b/wifi/1.3/default/tests/main.cpp new file mode 100644 index 0000000000..9aac837242 --- /dev/null +++ b/wifi/1.3/default/tests/main.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 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 <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <android-base/logging.h> + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::InitGoogleMock(&argc, argv); + // Force ourselves to always log to stderr + android::base::InitLogging(argv, android::base::StderrLogger); + return RUN_ALL_TESTS(); +} diff --git a/wifi/1.3/default/tests/mock_interface_tool.cpp b/wifi/1.3/default/tests/mock_interface_tool.cpp new file mode 100644 index 0000000000..b99a16446c --- /dev/null +++ b/wifi/1.3/default/tests/mock_interface_tool.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <gmock/gmock.h> + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "mock_interface_tool.h" + +namespace android { +namespace wifi_system { + +MockInterfaceTool::MockInterfaceTool() {} + +} // namespace wifi_system +} // namespace android diff --git a/wifi/1.3/default/tests/mock_interface_tool.h b/wifi/1.3/default/tests/mock_interface_tool.h new file mode 100644 index 0000000000..0f17551f96 --- /dev/null +++ b/wifi/1.3/default/tests/mock_interface_tool.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 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. + */ + +#ifndef MOCK_INTERFACE_TOOL_H +#define MOCK_INTERFACE_TOOL_H + +#include <gmock/gmock.h> +#include <wifi_system/interface_tool.h> + +namespace android { +namespace wifi_system { + +class MockInterfaceTool : public InterfaceTool { + public: + MockInterfaceTool(); + + MOCK_METHOD1(GetUpState, bool(const char* if_name)); + MOCK_METHOD2(SetUpState, bool(const char* if_name, bool request_up)); + MOCK_METHOD1(SetWifiUpState, bool(bool request_up)); + MOCK_METHOD2(SetMacAddress, + bool(const char* if_name, + const std::array<uint8_t, ETH_ALEN>& address)); + MOCK_METHOD1(GetFactoryMacAddress, + std::array<uint8_t, ETH_ALEN>(const char* if_name)); + +}; // class MockInterfaceTool + +} // namespace wifi_system +} // namespace android + +#endif // MOCK_INTERFACE_TOOL_H diff --git a/wifi/1.3/default/tests/mock_wifi_feature_flags.cpp b/wifi/1.3/default/tests/mock_wifi_feature_flags.cpp new file mode 100644 index 0000000000..a393fdc539 --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_feature_flags.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 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 <gmock/gmock.h> + +#include "mock_wifi_feature_flags.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace feature_flags { + +MockWifiFeatureFlags::MockWifiFeatureFlags() {} + +} // namespace feature_flags +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/mock_wifi_feature_flags.h b/wifi/1.3/default/tests/mock_wifi_feature_flags.h new file mode 100644 index 0000000000..ee12b54c78 --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_feature_flags.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2017 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. + */ + +#ifndef MOCK_WIFI_FEATURE_FLAGS_H_ +#define MOCK_WIFI_FEATURE_FLAGS_H_ + +#include <gmock/gmock.h> +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 + +#include "wifi_feature_flags.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace feature_flags { + +class MockWifiFeatureFlags : public WifiFeatureFlags { + public: + MockWifiFeatureFlags(); + + MOCK_METHOD0(getChipModes, std::vector<V1_0::IWifiChip::ChipMode>()); + MOCK_METHOD0(isApMacRandomizationDisabled, bool()); +}; + +} // namespace feature_flags +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // MOCK_WIFI_FEATURE_FLAGS_H_ diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.cpp b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp new file mode 100644 index 0000000000..3d877c0cbf --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <gmock/gmock.h> + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "mock_wifi_iface_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace iface_util { + +MockWifiIfaceUtil::MockWifiIfaceUtil( + const std::weak_ptr<wifi_system::InterfaceTool> iface_tool) + : WifiIfaceUtil(iface_tool) {} +} // namespace iface_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.h b/wifi/1.3/default/tests/mock_wifi_iface_util.h new file mode 100644 index 0000000000..8ec93eb471 --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_iface_util.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 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. + */ + +#ifndef MOCK_WIFI_IFACE_UTIL_H_ +#define MOCK_WIFI_IFACE_UTIL_H_ + +#include <gmock/gmock.h> + +#include "wifi_iface_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace iface_util { + +class MockWifiIfaceUtil : public WifiIfaceUtil { + public: + MockWifiIfaceUtil( + const std::weak_ptr<wifi_system::InterfaceTool> iface_tool); + MOCK_METHOD1(getFactoryMacAddress, + std::array<uint8_t, 6>(const std::string&)); + MOCK_METHOD2(setMacAddress, + bool(const std::string&, const std::array<uint8_t, 6>&)); + MOCK_METHOD0(getOrCreateRandomMacAddress, std::array<uint8_t, 6>()); + MOCK_METHOD2(registerIfaceEventHandlers, + void(const std::string&, IfaceEventHandlers)); + MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&)); +}; +} // namespace iface_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // MOCK_WIFI_IFACE_UTIL_H_ diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp new file mode 100644 index 0000000000..0a202c42d2 --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <gmock/gmock.h> + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "mock_wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace legacy_hal { + +MockWifiLegacyHal::MockWifiLegacyHal( + const std::weak_ptr<wifi_system::InterfaceTool> iface_tool) + : WifiLegacyHal(iface_tool) {} +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h new file mode 100644 index 0000000000..81cb1ded86 --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2017 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. + */ + +#ifndef MOCK_WIFI_LEGACY_HAL_H_ +#define MOCK_WIFI_LEGACY_HAL_H_ + +#include <gmock/gmock.h> + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace legacy_hal { + +class MockWifiLegacyHal : public WifiLegacyHal { + public: + MockWifiLegacyHal( + const std::weak_ptr<wifi_system::InterfaceTool> iface_tool); + MOCK_METHOD0(initialize, wifi_error()); + MOCK_METHOD0(start, wifi_error()); + MOCK_METHOD2(stop, wifi_error(std::unique_lock<std::recursive_mutex>*, + const std::function<void()>&)); + MOCK_METHOD2(setDfsFlag, wifi_error(const std::string&, bool)); + MOCK_METHOD2(registerRadioModeChangeCallbackHandler, + wifi_error(const std::string&, + const on_radio_mode_change_callback&)); + MOCK_METHOD1(getFirmwareVersion, std::pair<wifi_error, std::string>( + const std::string& iface_name)); + MOCK_METHOD1(getDriverVersion, std::pair<wifi_error, std::string>( + const std::string& iface_name)); + + MOCK_METHOD2(selectTxPowerScenario, + wifi_error(const std::string& iface_name, + wifi_power_scenario scenario)); + MOCK_METHOD1(resetTxPowerScenario, + wifi_error(const std::string& iface_name)); + MOCK_METHOD2(nanRegisterCallbackHandlers, + wifi_error(const std::string&, const NanCallbackHandlers&)); + MOCK_METHOD2(nanDisableRequest, + wifi_error(const std::string&, transaction_id)); + MOCK_METHOD3(nanDataInterfaceDelete, + wifi_error(const std::string&, transaction_id, + const std::string&)); +}; +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // MOCK_WIFI_LEGACY_HAL_H_ diff --git a/wifi/1.3/default/tests/mock_wifi_mode_controller.cpp b/wifi/1.3/default/tests/mock_wifi_mode_controller.cpp new file mode 100644 index 0000000000..2b0ea366f3 --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_mode_controller.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <gmock/gmock.h> + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "mock_wifi_mode_controller.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace mode_controller { + +MockWifiModeController::MockWifiModeController() : WifiModeController() {} +} // namespace mode_controller +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/mock_wifi_mode_controller.h b/wifi/1.3/default/tests/mock_wifi_mode_controller.h new file mode 100644 index 0000000000..c204059e67 --- /dev/null +++ b/wifi/1.3/default/tests/mock_wifi_mode_controller.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2017 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. + */ + +#ifndef MOCK_WIFI_MODE_CONTROLLER_H_ +#define MOCK_WIFI_MODE_CONTROLLER_H_ + +#include <gmock/gmock.h> + +#include "wifi_mode_controller.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace mode_controller { + +class MockWifiModeController : public WifiModeController { + public: + MockWifiModeController(); + MOCK_METHOD0(initialize, bool()); + MOCK_METHOD1(changeFirmwareMode, bool(IfaceType)); + MOCK_METHOD1(isFirmwareModeChangeNeeded, bool(IfaceType)); + MOCK_METHOD0(deinitialize, bool()); +}; +} // namespace mode_controller +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // MOCK_WIFI_MODE_CONTROLLER_H_ diff --git a/wifi/1.3/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.3/default/tests/ringbuffer_unit_tests.cpp new file mode 100644 index 0000000000..0cf1e4f256 --- /dev/null +++ b/wifi/1.3/default/tests/ringbuffer_unit_tests.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2018, 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 <gmock/gmock.h> + +#include "ringbuffer.h" + +using testing::Return; +using testing::Test; + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +class RingbufferTest : public Test { + public: + const uint32_t maxBufferSize_ = 10; + Ringbuffer buffer_{maxBufferSize_}; +}; + +TEST_F(RingbufferTest, CreateEmptyBuffer) { + ASSERT_TRUE(buffer_.getData().empty()); +} + +TEST_F(RingbufferTest, CanUseFullBufferCapacity) { + const std::vector<uint8_t> input(maxBufferSize_ / 2, '0'); + const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1'); + buffer_.append(input); + buffer_.append(input2); + ASSERT_EQ(2u, buffer_.getData().size()); + EXPECT_EQ(input, buffer_.getData().front()); + EXPECT_EQ(input2, buffer_.getData().back()); +} + +TEST_F(RingbufferTest, OldDataIsRemovedOnOverflow) { + const std::vector<uint8_t> input(maxBufferSize_ / 2, '0'); + const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1'); + const std::vector<uint8_t> input3 = {'G'}; + buffer_.append(input); + buffer_.append(input2); + buffer_.append(input3); + ASSERT_EQ(2u, buffer_.getData().size()); + EXPECT_EQ(input2, buffer_.getData().front()); + EXPECT_EQ(input3, buffer_.getData().back()); +} + +TEST_F(RingbufferTest, MultipleOldDataIsRemovedOnOverflow) { + const std::vector<uint8_t> input(maxBufferSize_ / 2, '0'); + const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1'); + const std::vector<uint8_t> input3(maxBufferSize_, '2'); + buffer_.append(input); + buffer_.append(input2); + buffer_.append(input3); + ASSERT_EQ(1u, buffer_.getData().size()); + EXPECT_EQ(input3, buffer_.getData().front()); +} + +TEST_F(RingbufferTest, AppendingEmptyBufferDoesNotAddGarbage) { + const std::vector<uint8_t> input = {}; + buffer_.append(input); + ASSERT_TRUE(buffer_.getData().empty()); +} + +TEST_F(RingbufferTest, OversizedAppendIsDropped) { + const std::vector<uint8_t> input(maxBufferSize_ + 1, '0'); + buffer_.append(input); + ASSERT_TRUE(buffer_.getData().empty()); +} + +TEST_F(RingbufferTest, OversizedAppendDoesNotDropExistingData) { + const std::vector<uint8_t> input(maxBufferSize_, '0'); + const std::vector<uint8_t> input2(maxBufferSize_ + 1, '1'); + buffer_.append(input); + buffer_.append(input2); + ASSERT_EQ(1u, buffer_.getData().size()); + EXPECT_EQ(input, buffer_.getData().front()); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/runtests.sh b/wifi/1.3/default/tests/runtests.sh new file mode 100755 index 0000000000..6bce3ef8c4 --- /dev/null +++ b/wifi/1.3/default/tests/runtests.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# Copyright(C) 2017 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. + +if [ -z $ANDROID_BUILD_TOP ]; then + echo "You need to source and lunch before you can use this script" + exit 1 +fi +set -e + +$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode android.hardware.wifi@1.0-service-tests +adb root +adb sync data +adb shell /data/nativetest64/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests diff --git a/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp new file mode 100644 index 0000000000..680f534c41 --- /dev/null +++ b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2019, 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <cutils/properties.h> +#include <gmock/gmock.h> + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "wifi_ap_iface.h" + +#include "mock_interface_tool.h" +#include "mock_wifi_feature_flags.h" +#include "mock_wifi_iface_util.h" +#include "mock_wifi_legacy_hal.h" + +using testing::NiceMock; +using testing::Return; +using testing::Test; + +namespace { +constexpr char kIfaceName[] = "mockWlan0"; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +class WifiApIfaceTest : public Test { + protected: + std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{ + new NiceMock<wifi_system::MockInterfaceTool>}; + std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{ + new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)}; + std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{ + new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)}; + std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>> + feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>}; +}; + +TEST_F(WifiApIfaceTest, SetRandomMacAddressIfFeatureEnabled) { + EXPECT_CALL(*feature_flags_, isApMacRandomizationDisabled()) + .WillOnce(testing::Return(false)); + EXPECT_CALL(*iface_util_, getOrCreateRandomMacAddress()) + .WillOnce(testing::Return(std::array<uint8_t, 6>{0, 0, 0, 0, 0, 0})); + EXPECT_CALL(*iface_util_, setMacAddress(testing::_, testing::_)) + .WillOnce(testing::Return(true)); + sp<WifiApIface> ap_iface = + new WifiApIface(kIfaceName, legacy_hal_, iface_util_, feature_flags_); +} + +TEST_F(WifiApIfaceTest, DontSetRandomMacAddressIfFeatureDisabled) { + EXPECT_CALL(*feature_flags_, isApMacRandomizationDisabled()) + .WillOnce(testing::Return(true)); + EXPECT_CALL(*iface_util_, getOrCreateRandomMacAddress()).Times(0); + EXPECT_CALL(*iface_util_, setMacAddress(testing::_, testing::_)).Times(0); + sp<WifiApIface> ap_iface = + new WifiApIface(kIfaceName, legacy_hal_, iface_util_, feature_flags_); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp new file mode 100644 index 0000000000..d8ce2785b7 --- /dev/null +++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp @@ -0,0 +1,871 @@ +/* + * Copyright (C) 2017, 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <cutils/properties.h> +#include <gmock/gmock.h> + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "wifi_chip.h" + +#include "mock_interface_tool.h" +#include "mock_wifi_feature_flags.h" +#include "mock_wifi_iface_util.h" +#include "mock_wifi_legacy_hal.h" +#include "mock_wifi_mode_controller.h" + +using testing::NiceMock; +using testing::Return; +using testing::Test; + +namespace { +using android::hardware::wifi::V1_0::ChipId; + +constexpr ChipId kFakeChipId = 5; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +class WifiChipTest : public Test { + protected: + void setupV1IfaceCombination() { + // clang-format off + const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinationsSta = { + {{{{IfaceType::STA}, 1}, {{IfaceType::P2P}, 1}}} + }; + const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinationsAp = { + {{{{IfaceType::AP}, 1}}} + }; + const std::vector<V1_0::IWifiChip::ChipMode> modes = { + {feature_flags::chip_mode_ids::kV1Sta, combinationsSta}, + {feature_flags::chip_mode_ids::kV1Ap, combinationsAp} + }; + // clang-format on + EXPECT_CALL(*feature_flags_, getChipModes()) + .WillRepeatedly(testing::Return(modes)); + } + + void setupV1_AwareIfaceCombination() { + // clang-format off + const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinationsSta = { + {{{{IfaceType::STA}, 1}, {{IfaceType::P2P, IfaceType::NAN}, 1}}} + }; + const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinationsAp = { + {{{{IfaceType::AP}, 1}}} + }; + const std::vector<V1_0::IWifiChip::ChipMode> modes = { + {feature_flags::chip_mode_ids::kV1Sta, combinationsSta}, + {feature_flags::chip_mode_ids::kV1Ap, combinationsAp} + }; + // clang-format on + EXPECT_CALL(*feature_flags_, getChipModes()) + .WillRepeatedly(testing::Return(modes)); + } + + void setupV1_AwareDisabledApIfaceCombination() { + // clang-format off + const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinationsSta = { + {{{{IfaceType::STA}, 1}, {{IfaceType::P2P, IfaceType::NAN}, 1}}} + }; + const std::vector<V1_0::IWifiChip::ChipMode> modes = { + {feature_flags::chip_mode_ids::kV1Sta, combinationsSta} + }; + // clang-format on + EXPECT_CALL(*feature_flags_, getChipModes()) + .WillRepeatedly(testing::Return(modes)); + } + + void setupV2_AwareIfaceCombination() { + // clang-format off + const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinations = { + {{{{IfaceType::STA}, 1}, {{IfaceType::AP}, 1}}}, + {{{{IfaceType::STA}, 1}, {{IfaceType::P2P, IfaceType::NAN}, 1}}} + }; + const std::vector<V1_0::IWifiChip::ChipMode> modes = { + {feature_flags::chip_mode_ids::kV3, combinations} + }; + // clang-format on + EXPECT_CALL(*feature_flags_, getChipModes()) + .WillRepeatedly(testing::Return(modes)); + } + + void setupV2_AwareDisabledApIfaceCombination() { + // clang-format off + const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinations = { + {{{{IfaceType::STA}, 1}, {{IfaceType::P2P, IfaceType::NAN}, 1}}} + }; + const std::vector<V1_0::IWifiChip::ChipMode> modes = { + {feature_flags::chip_mode_ids::kV3, combinations} + }; + // clang-format on + EXPECT_CALL(*feature_flags_, getChipModes()) + .WillRepeatedly(testing::Return(modes)); + } + + void setup_MultiIfaceCombination() { + // clang-format off + const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinations = { + {{{{IfaceType::STA}, 3}, {{IfaceType::AP}, 1}}} + }; + const std::vector<V1_0::IWifiChip::ChipMode> modes = { + {feature_flags::chip_mode_ids::kV3, combinations} + }; + // clang-format on + EXPECT_CALL(*feature_flags_, getChipModes()) + .WillRepeatedly(testing::Return(modes)); + } + + void assertNumberOfModes(uint32_t num_modes) { + chip_->getAvailableModes( + [num_modes](const WifiStatus& status, + const std::vector<WifiChip::ChipMode>& modes) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + // V2_Aware has 1 mode of operation. + ASSERT_EQ(num_modes, modes.size()); + }); + } + + void findModeAndConfigureForIfaceType(const IfaceType& type) { + // This should be aligned with kInvalidModeId in wifi_chip.cpp. + ChipModeId mode_id = UINT32_MAX; + chip_->getAvailableModes( + [&mode_id, &type](const WifiStatus& status, + const std::vector<WifiChip::ChipMode>& modes) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + for (const auto& mode : modes) { + for (const auto& combination : mode.availableCombinations) { + for (const auto& limit : combination.limits) { + if (limit.types.end() != + std::find(limit.types.begin(), + limit.types.end(), type)) { + mode_id = mode.id; + } + } + } + } + }); + ASSERT_NE(UINT32_MAX, mode_id); + + chip_->configureChip(mode_id, [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); + } + + // Returns an empty string on error. + std::string createIface(const IfaceType& type) { + std::string iface_name; + if (type == IfaceType::AP) { + chip_->createApIface([&iface_name](const WifiStatus& status, + const sp<IWifiApIface>& iface) { + if (WifiStatusCode::SUCCESS == status.code) { + ASSERT_NE(iface.get(), nullptr); + iface->getName([&iface_name](const WifiStatus& status, + const hidl_string& name) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + iface_name = name.c_str(); + }); + } + }); + } else if (type == IfaceType::NAN) { + chip_->createNanIface( + [&iface_name]( + const WifiStatus& status, + const sp<android::hardware::wifi::V1_0::IWifiNanIface>& + iface) { + if (WifiStatusCode::SUCCESS == status.code) { + ASSERT_NE(iface.get(), nullptr); + iface->getName([&iface_name](const WifiStatus& status, + const hidl_string& name) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + iface_name = name.c_str(); + }); + } + }); + } else if (type == IfaceType::P2P) { + chip_->createP2pIface( + [&iface_name](const WifiStatus& status, + const sp<IWifiP2pIface>& iface) { + if (WifiStatusCode::SUCCESS == status.code) { + ASSERT_NE(iface.get(), nullptr); + iface->getName([&iface_name](const WifiStatus& status, + const hidl_string& name) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + iface_name = name.c_str(); + }); + } + }); + } else if (type == IfaceType::STA) { + chip_->createStaIface( + [&iface_name](const WifiStatus& status, + const sp<V1_0::IWifiStaIface>& iface) { + if (WifiStatusCode::SUCCESS == status.code) { + ASSERT_NE(iface.get(), nullptr); + iface->getName([&iface_name](const WifiStatus& status, + const hidl_string& name) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + iface_name = name.c_str(); + }); + } + }); + } + return iface_name; + } + + void removeIface(const IfaceType& type, const std::string& iface_name) { + if (type == IfaceType::AP) { + chip_->removeApIface(iface_name, [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); + } else if (type == IfaceType::NAN) { + chip_->removeNanIface(iface_name, [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); + } else if (type == IfaceType::P2P) { + chip_->removeP2pIface(iface_name, [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); + } else if (type == IfaceType::STA) { + chip_->removeStaIface(iface_name, [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); + } + } + + bool createRttController() { + bool success = false; + chip_->createRttController( + NULL, [&success](const WifiStatus& status, + const sp<IWifiRttController>& rtt) { + if (WifiStatusCode::SUCCESS == status.code) { + ASSERT_NE(rtt.get(), nullptr); + success = true; + } + }); + return success; + } + + sp<WifiChip> chip_; + ChipId chip_id_ = kFakeChipId; + std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{ + new NiceMock<wifi_system::MockInterfaceTool>}; + std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{ + new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)}; + std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>> + mode_controller_{new NiceMock<mode_controller::MockWifiModeController>}; + std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{ + new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)}; + std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>> + feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>}; + + public: + void SetUp() override { + chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_, + iface_util_, feature_flags_); + + EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_)) + .WillRepeatedly(testing::Return(true)); + EXPECT_CALL(*legacy_hal_, start()) + .WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS)); + } + + void TearDown() override { + // Restore default system iface names (This should ideally be using a + // mock). + property_set("wifi.interface", "wlan0"); + property_set("wifi.concurrent.interface", "wlan1"); + } +}; + +////////// V1 Iface Combinations //////////// +// Mode 1 - STA + P2P +// Mode 2 - AP +class WifiChipV1IfaceCombinationTest : public WifiChipTest { + public: + void SetUp() override { + setupV1IfaceCombination(); + WifiChipTest::SetUp(); + // V1 has 2 modes of operation. + assertNumberOfModes(2u); + } +}; + +TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); +} + +TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateNan_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_TRUE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateAp_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_TRUE(createIface(IfaceType::AP).empty()); +} + +TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateStaP2p_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::AP), "wlan0"); +} + +TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateSta_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_TRUE(createIface(IfaceType::STA).empty()); +} + +TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateP2p_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_TRUE(createIface(IfaceType::STA).empty()); +} + +TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateNan_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_TRUE(createIface(IfaceType::NAN).empty()); +} + +////////// V1 + Aware Iface Combinations //////////// +// Mode 1 - STA + P2P/NAN +// Mode 2 - AP +class WifiChipV1_AwareIfaceCombinationTest : public WifiChipTest { + public: + void SetUp() override { + setupV1_AwareIfaceCombination(); + WifiChipTest::SetUp(); + // V1_Aware has 2 modes of operation. + assertNumberOfModes(2u); + } +}; + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateNan_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateAp_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_TRUE(createIface(IfaceType::AP).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, + StaMode_CreateStaP2p_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, + StaMode_CreateStaNan_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, + StaMode_CreateStaP2PNan_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); + ASSERT_TRUE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, + StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + const auto p2p_iface_name = createIface(IfaceType::P2P); + ASSERT_FALSE(p2p_iface_name.empty()); + ASSERT_TRUE(createIface(IfaceType::NAN).empty()); + + // After removing P2P iface, NAN iface creation should succeed. + removeIface(IfaceType::P2P, p2p_iface_name); + ASSERT_FALSE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, + StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + const auto nan_iface_name = createIface(IfaceType::NAN); + ASSERT_FALSE(nan_iface_name.empty()); + ASSERT_TRUE(createIface(IfaceType::P2P).empty()); + + // After removing NAN iface, P2P iface creation should succeed. + removeIface(IfaceType::NAN, nan_iface_name); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::AP), "wlan0"); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateSta_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_TRUE(createIface(IfaceType::STA).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateP2p_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_TRUE(createIface(IfaceType::STA).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateNan_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_TRUE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_TRUE(createRttController()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_TRUE(createRttController()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowApToSta) { + findModeAndConfigureForIfaceType(IfaceType::AP); + const auto ap_iface_name = createIface(IfaceType::AP); + ASSERT_FALSE(ap_iface_name.empty()); + ASSERT_FALSE(createRttController()); + + removeIface(IfaceType::AP, ap_iface_name); + + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_TRUE(createRttController()); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + chip_->selectTxPowerScenario_1_2( + V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF, + [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); +} + +TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::AP), "wlan0"); + EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + chip_->selectTxPowerScenario_1_2( + V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF, + [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); +} + +////////// V2 + Aware Iface Combinations //////////// +// Mode 1 - STA + STA/AP +// - STA + P2P/NAN +class WifiChipV2_AwareIfaceCombinationTest : public WifiChipTest { + public: + void SetUp() override { + setupV2_AwareIfaceCombination(); + WifiChipTest::SetUp(); + // V2_Aware has 1 mode of operation. + assertNumberOfModes(1u); + } +}; + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateP2p_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNan_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateAp_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaSta_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + ASSERT_TRUE(createIface(IfaceType::STA).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApSta_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + CreateSta_AfterStaApRemove_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + const auto sta_iface_name = createIface(IfaceType::STA); + ASSERT_FALSE(sta_iface_name.empty()); + const auto ap_iface_name = createIface(IfaceType::AP); + ASSERT_FALSE(ap_iface_name.empty()); + + ASSERT_TRUE(createIface(IfaceType::STA).empty()); + + // After removing AP & STA iface, STA iface creation should succeed. + removeIface(IfaceType::STA, sta_iface_name); + removeIface(IfaceType::AP, ap_iface_name); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2p_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaNan_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2PNan_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); + ASSERT_TRUE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + CreateStaNan_AfterP2pRemove_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + const auto p2p_iface_name = createIface(IfaceType::P2P); + ASSERT_FALSE(p2p_iface_name.empty()); + ASSERT_TRUE(createIface(IfaceType::NAN).empty()); + + // After removing P2P iface, NAN iface creation should succeed. + removeIface(IfaceType::P2P, p2p_iface_name); + ASSERT_FALSE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + CreateStaP2p_AfterNanRemove_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + const auto nan_iface_name = createIface(IfaceType::NAN); + ASSERT_FALSE(nan_iface_name.empty()); + ASSERT_TRUE(createIface(IfaceType::P2P).empty()); + + // After removing NAN iface, P2P iface creation should succeed. + removeIface(IfaceType::NAN, nan_iface_name); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApNan_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_FALSE(createIface(IfaceType::AP).empty()); + ASSERT_TRUE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApP2p_ShouldFail) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_FALSE(createIface(IfaceType::AP).empty()); + ASSERT_TRUE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + const auto p2p_iface_name = createIface(IfaceType::P2P); + ASSERT_FALSE(p2p_iface_name.empty()); + ASSERT_TRUE(createIface(IfaceType::NAN).empty()); + + // After removing P2P iface, NAN iface creation should succeed. + removeIface(IfaceType::P2P, p2p_iface_name); + ASSERT_FALSE(createIface(IfaceType::NAN).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + const auto nan_iface_name = createIface(IfaceType::NAN); + ASSERT_FALSE(nan_iface_name.empty()); + ASSERT_TRUE(createIface(IfaceType::P2P).empty()); + + // After removing NAN iface, P2P iface creation should succeed. + removeIface(IfaceType::NAN, nan_iface_name); + ASSERT_FALSE(createIface(IfaceType::P2P).empty()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + CreateStaAp_EnsureDifferentIfaceNames) { + findModeAndConfigureForIfaceType(IfaceType::AP); + const auto sta_iface_name = createIface(IfaceType::STA); + const auto ap_iface_name = createIface(IfaceType::AP); + ASSERT_FALSE(sta_iface_name.empty()); + ASSERT_FALSE(ap_iface_name.empty()); + ASSERT_NE(sta_iface_name, ap_iface_name); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_TRUE(createRttController()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_TRUE(createRttController()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlow) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::AP).empty()); + ASSERT_TRUE(createRttController()); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + chip_->selectTxPowerScenario_1_2( + V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF, + [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) { + findModeAndConfigureForIfaceType(IfaceType::AP); + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); + EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan1", testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + chip_->selectTxPowerScenario_1_2( + V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF, + [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + InvalidateAndRemoveNanOnStaRemove) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + + // Create NAN iface + ASSERT_EQ(createIface(IfaceType::NAN), "wlan0"); + + // We should have 1 nan iface. + chip_->getNanIfaceNames( + [](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + ASSERT_EQ(iface_names.size(), 1u); + ASSERT_EQ(iface_names[0], "wlan0"); + }); + // Retrieve the exact iface object. + sp<IWifiNanIface> nan_iface; + chip_->getNanIface("wlan0", [&nan_iface](const WifiStatus& status, + const sp<IWifiNanIface>& iface) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + ASSERT_NE(iface.get(), nullptr); + nan_iface = iface; + }); + + // Remove the STA iface. + removeIface(IfaceType::STA, "wlan0"); + // We should have 0 nan iface now. + chip_->getNanIfaceNames( + [](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + ASSERT_EQ(iface_names.size(), 0u); + }); + // Any operation on the nan iface object should return error now. + nan_iface->getName( + [](const WifiStatus& status, const std::string& /* iface_name */) { + ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID, status.code); + }); +} + +TEST_F(WifiChipV2_AwareIfaceCombinationTest, + InvalidateAndRemoveRttControllerOnStaRemove) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + + // Create RTT controller + sp<IWifiRttController> rtt_controller; + chip_->createRttController( + NULL, [&rtt_controller](const WifiStatus& status, + const sp<IWifiRttController>& rtt) { + if (WifiStatusCode::SUCCESS == status.code) { + ASSERT_NE(rtt.get(), nullptr); + rtt_controller = rtt; + } + }); + + // Remove the STA iface. + removeIface(IfaceType::STA, "wlan0"); + + // Any operation on the rtt controller object should return error now. + rtt_controller->getBoundIface( + [](const WifiStatus& status, const sp<IWifiIface>& /* iface */) { + ASSERT_EQ(WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + status.code); + }); +} + +////////// V1 Iface Combinations when AP creation is disabled ////////// +class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest { + public: + void SetUp() override { + setupV1_AwareDisabledApIfaceCombination(); + WifiChipTest::SetUp(); + } +}; + +TEST_F(WifiChipV1_AwareDisabledApIfaceCombinationTest, + StaMode_CreateSta_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_TRUE(createIface(IfaceType::AP).empty()); +} + +////////// V2 Iface Combinations when AP creation is disabled ////////// +class WifiChipV2_AwareDisabledApIfaceCombinationTest : public WifiChipTest { + public: + void SetUp() override { + setupV2_AwareDisabledApIfaceCombination(); + WifiChipTest::SetUp(); + } +}; + +TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest, + CreateSta_ShouldSucceed) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_TRUE(createIface(IfaceType::AP).empty()); +} + +////////// Hypothetical Iface Combination with multiple ifaces ////////// +class WifiChip_MultiIfaceTest : public WifiChipTest { + public: + void SetUp() override { + setup_MultiIfaceCombination(); + WifiChipTest::SetUp(); + } +}; + +TEST_F(WifiChip_MultiIfaceTest, Create3Sta) { + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_FALSE(createIface(IfaceType::STA).empty()); + ASSERT_TRUE(createIface(IfaceType::STA).empty()); +} + +TEST_F(WifiChip_MultiIfaceTest, CreateStaWithDefaultNames) { + property_set("wifi.interface.0", ""); + property_set("wifi.interface.1", ""); + property_set("wifi.interface.2", ""); + property_set("wifi.interface", ""); + property_set("wifi.concurrent.interface", ""); + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + ASSERT_EQ(createIface(IfaceType::STA), "wlan1"); + ASSERT_EQ(createIface(IfaceType::STA), "wlan2"); +} + +TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomNames) { + property_set("wifi.interface.0", "test0"); + property_set("wifi.interface.1", "test1"); + property_set("wifi.interface.2", "test2"); + property_set("wifi.interface", "bad0"); + property_set("wifi.concurrent.interface", "bad1"); + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "bad0"); + ASSERT_EQ(createIface(IfaceType::STA), "bad1"); + ASSERT_EQ(createIface(IfaceType::STA), "test2"); +} + +TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomAltNames) { + property_set("wifi.interface.0", ""); + property_set("wifi.interface.1", ""); + property_set("wifi.interface.2", ""); + property_set("wifi.interface", "testA0"); + property_set("wifi.concurrent.interface", "testA1"); + findModeAndConfigureForIfaceType(IfaceType::STA); + ASSERT_EQ(createIface(IfaceType::STA), "testA0"); + ASSERT_EQ(createIface(IfaceType::STA), "testA1"); + ASSERT_EQ(createIface(IfaceType::STA), "wlan2"); +} + +TEST_F(WifiChip_MultiIfaceTest, CreateApStartsWithIdx1) { + findModeAndConfigureForIfaceType(IfaceType::STA); + // First AP will be slotted to wlan1. + ASSERT_EQ(createIface(IfaceType::AP), "wlan1"); + // First STA will be slotted to wlan0. + ASSERT_EQ(createIface(IfaceType::STA), "wlan0"); + // All further STA will be slotted to the remaining free indices. + ASSERT_EQ(createIface(IfaceType::STA), "wlan2"); + ASSERT_EQ(createIface(IfaceType::STA), "wlan3"); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp new file mode 100644 index 0000000000..28d23ffa71 --- /dev/null +++ b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019, 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <gmock/gmock.h> + +#undef NAN +#include "wifi_iface_util.h" + +#include "mock_interface_tool.h" + +using testing::NiceMock; +using testing::Test; + +namespace { +constexpr uint8_t kValidUnicastLocallyAssignedMacAddressMask = 0x02; +constexpr uint8_t kMacAddress[] = {0x02, 0x12, 0x45, 0x56, 0xab, 0xcc}; +constexpr char kIfaceName[] = "test-wlan0"; + +bool isValidUnicastLocallyAssignedMacAddress( + const std::array<uint8_t, 6>& mac_address) { + uint8_t first_byte = mac_address[0]; + return (first_byte & 0x3) == kValidUnicastLocallyAssignedMacAddressMask; +} +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace iface_util { +class WifiIfaceUtilTest : public Test { + protected: + std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{ + new NiceMock<wifi_system::MockInterfaceTool>}; + WifiIfaceUtil* iface_util_ = new WifiIfaceUtil(iface_tool_); +}; + +TEST_F(WifiIfaceUtilTest, GetOrCreateRandomMacAddress) { + auto mac_address = iface_util_->getOrCreateRandomMacAddress(); + ASSERT_TRUE(isValidUnicastLocallyAssignedMacAddress(mac_address)); + + // All further calls should return the same MAC address. + ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress()); + ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress()); +} + +TEST_F(WifiIfaceUtilTest, IfaceEventHandlers_SetMacAddress) { + std::array<uint8_t, 6> mac_address = {}; + std::copy(std::begin(kMacAddress), std::end(kMacAddress), + std::begin(mac_address)); + EXPECT_CALL(*iface_tool_, SetMacAddress(testing::_, testing::_)) + .WillRepeatedly(testing::Return(true)); + EXPECT_CALL(*iface_tool_, SetUpState(testing::_, testing::_)) + .WillRepeatedly(testing::Return(true)); + + // Register for iface state toggle events. + bool callback_invoked = false; + iface_util::IfaceEventHandlers event_handlers = {}; + event_handlers.on_state_toggle_off_on = + [&callback_invoked](const std::string& /* iface_name */) { + callback_invoked = true; + }; + iface_util_->registerIfaceEventHandlers(kIfaceName, event_handlers); + // Invoke setMacAddress and ensure that the cb is invoked. + ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address)); + ASSERT_TRUE(callback_invoked); + + // Unregister for iface state toggle events. + callback_invoked = false; + iface_util_->unregisterIfaceEventHandlers(kIfaceName); + // Invoke setMacAddress and ensure that the cb is not invoked. + ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address)); + ASSERT_FALSE(callback_invoked); +} +} // namespace iface_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp new file mode 100644 index 0000000000..eb6c61065d --- /dev/null +++ b/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2019, 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 <android-base/logging.h> +#include <android-base/macros.h> +#include <cutils/properties.h> +#include <gmock/gmock.h> + +#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38 +#include "wifi_nan_iface.h" + +#include "mock_interface_tool.h" +#include "mock_wifi_feature_flags.h" +#include "mock_wifi_iface_util.h" +#include "mock_wifi_legacy_hal.h" + +using testing::NiceMock; +using testing::Return; +using testing::Test; + +namespace { +constexpr char kIfaceName[] = "mockWlan0"; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +bool CaptureIfaceEventHandlers( + const std::string& /* iface_name*/, + iface_util::IfaceEventHandlers in_iface_event_handlers, + iface_util::IfaceEventHandlers* out_iface_event_handlers) { + *out_iface_event_handlers = in_iface_event_handlers; + return true; +} + +class MockNanIfaceEventCallback : public IWifiNanIfaceEventCallback { + public: + MockNanIfaceEventCallback() = default; + + MOCK_METHOD3(notifyCapabilitiesResponse, + Return<void>(uint16_t, const WifiNanStatus&, + const NanCapabilities&)); + MOCK_METHOD2(notifyEnableResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyConfigResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyDisableResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD3(notifyStartPublishResponse, + Return<void>(uint16_t, const WifiNanStatus&, uint8_t)); + MOCK_METHOD2(notifyStopPublishResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD3(notifyStartSubscribeResponse, + Return<void>(uint16_t, const WifiNanStatus&, uint8_t)); + MOCK_METHOD2(notifyStopSubscribeResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyTransmitFollowupResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyCreateDataInterfaceResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyDeleteDataInterfaceResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD3(notifyInitiateDataPathResponse, + Return<void>(uint16_t, const WifiNanStatus&, uint32_t)); + MOCK_METHOD2(notifyRespondToDataPathIndicationResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD2(notifyTerminateDataPathResponse, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD1(eventClusterEvent, Return<void>(const NanClusterEventInd&)); + MOCK_METHOD1(eventDisabled, Return<void>(const WifiNanStatus&)); + MOCK_METHOD2(eventPublishTerminated, + Return<void>(uint8_t, const WifiNanStatus&)); + MOCK_METHOD2(eventSubscribeTerminated, + Return<void>(uint8_t, const WifiNanStatus&)); + MOCK_METHOD1(eventMatch, Return<void>(const NanMatchInd&)); + MOCK_METHOD2(eventMatchExpired, Return<void>(uint8_t, uint32_t)); + MOCK_METHOD1(eventFollowupReceived, + Return<void>(const NanFollowupReceivedInd&)); + MOCK_METHOD2(eventTransmitFollowup, + Return<void>(uint16_t, const WifiNanStatus&)); + MOCK_METHOD1(eventDataPathRequest, + Return<void>(const NanDataPathRequestInd&)); + MOCK_METHOD1(eventDataPathConfirm, + Return<void>(const NanDataPathConfirmInd&)); + MOCK_METHOD1(eventDataPathTerminated, Return<void>(uint32_t)); +}; + +class WifiNanIfaceTest : public Test { + protected: + std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{ + new NiceMock<wifi_system::MockInterfaceTool>}; + std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{ + new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)}; + std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{ + new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)}; +}; + +TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) { + iface_util::IfaceEventHandlers captured_iface_event_handlers = {}; + EXPECT_CALL(*legacy_hal_, + nanRegisterCallbackHandlers(testing::_, testing::_)) + .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS)); + EXPECT_CALL(*iface_util_, + registerIfaceEventHandlers(testing::_, testing::_)) + .WillOnce(testing::Invoke( + bind(CaptureIfaceEventHandlers, std::placeholders::_1, + std::placeholders::_2, &captured_iface_event_handlers))); + sp<WifiNanIface> nan_iface = + new WifiNanIface(kIfaceName, legacy_hal_, iface_util_); + + // Register a mock nan event callback. + sp<NiceMock<MockNanIfaceEventCallback>> mock_event_callback{ + new NiceMock<MockNanIfaceEventCallback>}; + nan_iface->registerEventCallback( + mock_event_callback, [](const WifiStatus& status) { + ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); + }); + // Ensure that the eventDisabled() function in mock callback will be + // invoked. + WifiNanStatus expected_nan_status = { + NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""}; + EXPECT_CALL(*mock_event_callback, eventDisabled(expected_nan_status)) + .Times(1); + + // Trigger the iface state toggle callback. + captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android |
