From 5fba090f1a56b9eec896915bbc34a93e6be8ae23 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 2 Jan 2018 11:24:32 -0800 Subject: [PATCH] hostapd(vts): VTS tests for the HIDL interface Bug: 36646171 Bug: 71613528 Test: `adb shell /data/VtsHalWifiHostapdV1_0TargetTest` Change-Id: I979296be7d97c6768c4fb76586025109758261ef --- wifi/hostapd/1.0/vts/functional/Android.bp | 52 ++++ .../VtsHalWifiHostapdV1_0TargetTest.cpp | 35 +++ .../vts/functional/hostapd_hidl_call_util.h | 127 ++++++++++ .../1.0/vts/functional/hostapd_hidl_test.cpp | 222 ++++++++++++++++++ .../functional/hostapd_hidl_test_utils.cpp | 135 +++++++++++ .../vts/functional/hostapd_hidl_test_utils.h | 36 +++ 6 files changed, 607 insertions(+) create mode 100644 wifi/hostapd/1.0/vts/functional/Android.bp create mode 100644 wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp create mode 100644 wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h create mode 100644 wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp create mode 100644 wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp create mode 100644 wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h diff --git a/wifi/hostapd/1.0/vts/functional/Android.bp b/wifi/hostapd/1.0/vts/functional/Android.bp new file mode 100644 index 0000000000..7a920b448a --- /dev/null +++ b/wifi/hostapd/1.0/vts/functional/Android.bp @@ -0,0 +1,52 @@ +// +// 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. +// + +cc_library_static { + name: "VtsHalWifiHostapdV1_0TargetTestUtil", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["hostapd_hidl_test_utils.cpp"], + export_include_dirs: [ + "." + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi@1.0", + "libcrypto", + "libgmock", + "libwifi-system", + "libwifi-system-iface", + ], +} + +cc_test { + name: "VtsHalWifiHostapdV1_0TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "VtsHalWifiHostapdV1_0TargetTest.cpp", + "hostapd_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "VtsHalWifiHostapdV1_0TargetTestUtil", + "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi@1.0", + "libcrypto", + "libgmock", + "libwifi-system", + "libwifi-system-iface", + ], +} diff --git a/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp b/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp new file mode 100644 index 0000000000..64e6fbe358 --- /dev/null +++ b/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 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 + +#include + +#include "hostapd_hidl_test_utils.h" + +class HostapdHidlEnvironment : public ::testing::Environment { + public: + virtual void SetUp() override { stopHostapd(); } + virtual void TearDown() override { startHostapdAndWaitForHidlService(); } +}; + +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(new HostapdHidlEnvironment); + ::testing::InitGoogleTest(&argc, argv); + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + return status; +} diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h new file mode 100644 index 0000000000..2f71ccba65 --- /dev/null +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h @@ -0,0 +1,127 @@ +/* + * 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. + */ + +// This file is copied from +// hardware/interfaces/wifi/1.0/vts/functional/wifi_hidl_call_util.h +// Please make sure these two file are consistent. + +#pragma once + +#include +#include +#include +#include + +#include + +namespace { +namespace detail { +template +struct functionArgSaver; + +// Provides a std::function that takes one argument, and a buffer +// wherein the function will store its argument. The buffer has +// the same type as the argument, but with const and reference +// modifiers removed. +template +struct functionArgSaver> final { + using StorageT = typename std::remove_const< + typename std::remove_reference::type>::type; + + std::function saveArgs = [this](ArgT arg) { + this->saved_values = arg; + }; + + StorageT saved_values; +}; + +// Provides a std::function that takes two arguments, and a buffer +// wherein the function will store its arguments. The buffer is a +// std::pair, whose elements have the same types as the arguments +// (but with const and reference modifiers removed). +template +struct functionArgSaver> final { + using StorageT = + std::pair::type>::type, + typename std::remove_const< + typename std::remove_reference::type>::type>; + + std::function saveArgs = [this](Arg1T arg1, + Arg2T arg2) { + this->saved_values = {arg1, arg2}; + }; + + StorageT saved_values; +}; + +// Provides a std::function that takes three or more arguments, and a +// buffer wherein the function will store its arguments. The buffer is a +// std::tuple whose elements have the same types as the arguments (but +// with const and reference modifiers removed). +template +struct functionArgSaver> final { + using StorageT = std::tuple::type>::type...>; + + std::function saveArgs = [this](ArgT... arg) { + this->saved_values = {arg...}; + }; + + StorageT saved_values; +}; + +// Invokes |method| on |object|, providing |method| a CallbackT as the +// final argument. Returns a copy of the parameters that |method| provided +// to CallbackT. (The parameters are returned by value.) +template +typename functionArgSaver::StorageT invokeMethod( + MethodT method, ObjectT object, ArgT&&... methodArg) { + functionArgSaver result_buffer; + const auto& res = ((*object).*method)(std::forward(methodArg)..., + result_buffer.saveArgs); + EXPECT_TRUE(res.isOk()); + return result_buffer.saved_values; +} +} // namespace detail +} // namespace + +// Invokes |method| on |strong_pointer|, passing provided arguments through to +// |method|. +// +// Returns either: +// - A copy of the result callback parameter (for callbacks with a single +// parameter), OR +// - A pair containing a copy of the result callback parameters (for callbacks +// with two parameters), OR +// - A tuple containing a copy of the result callback paramters (for callbacks +// with three or more parameters). +// +// Example usage: +// EXPECT_EQ(HostapdStatusCode::SUCCESS, +// HIDL_INVOKE(strong_pointer, methodReturningHostapdStatus).code); +// EXPECT_EQ(HostapdStatusCode::SUCCESS, +// HIDL_INVOKE(strong_pointer, methodReturningHostapdStatusAndOneMore) +// .first.code); +// EXPECT_EQ(HostapdStatusCode::SUCCESS, std::get<0>( +// HIDL_INVOKE(strong_pointer, methodReturningHostapdStatusAndTwoMore)) +// .code); +#define HIDL_INVOKE(strong_pointer, method, ...) \ + (detail::invokeMethod< \ + std::remove_reference::type::method##_cb>( \ + &std::remove_reference::type::method, \ + strong_pointer, ##__VA_ARGS__)) diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp new file mode 100644 index 0000000000..5f51cfbd04 --- /dev/null +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2016 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 +#include + +#include + +#include + +#include "hostapd_hidl_call_util.h" +#include "hostapd_hidl_test_utils.h" + +using ::android::sp; +using ::android::hardware::hidl_vec; +using ::android::hardware::wifi::hostapd::V1_0::IHostapd; +using ::android::hardware::wifi::hostapd::V1_0::HostapdStatus; +using ::android::hardware::wifi::hostapd::V1_0::HostapdStatusCode; + +namespace { +constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1', + '2', '3', '4', '5'}; +constexpr char kNwPassphrase[] = "test12345"; +constexpr int kIfaceChannel = 6; +constexpr int kIfaceInvalidChannel = 567; +} // namespace + +class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase { + public: + virtual void SetUp() override { + startHostapdAndWaitForHidlService(); + hostapd_ = getHostapd(); + ASSERT_NE(hostapd_.get(), nullptr); + } + + virtual void TearDown() override { stopHostapd(); } + + protected: + std::string getPrimaryWlanIfaceName() { + std::array buffer; + property_get("wifi.interface", buffer.data(), "wlan0"); + return buffer.data(); + } + + IHostapd::IfaceParams getIfaceParamsWithAcs() { + IHostapd::IfaceParams iface_params; + iface_params.ifaceName = getPrimaryWlanIfaceName(); + iface_params.hwModeParams.enable80211N = true; + iface_params.hwModeParams.enable80211AC = false; + iface_params.channelParams.enableAcs = true; + iface_params.channelParams.acsShouldExcludeDfs = true; + iface_params.channelParams.channel = 0; + iface_params.channelParams.band = IHostapd::Band::BAND_ANY; + return iface_params; + } + + IHostapd::IfaceParams getIfaceParamsWithoutAcs() { + IHostapd::IfaceParams iface_params; + iface_params.ifaceName = getPrimaryWlanIfaceName(); + iface_params.hwModeParams.enable80211N = true; + iface_params.hwModeParams.enable80211AC = false; + iface_params.channelParams.enableAcs = false; + iface_params.channelParams.acsShouldExcludeDfs = false; + iface_params.channelParams.channel = kIfaceChannel; + iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ; + return iface_params; + } + + IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() { + IHostapd::IfaceParams iface_params; + iface_params.ifaceName = getPrimaryWlanIfaceName(); + iface_params.hwModeParams.enable80211N = true; + iface_params.hwModeParams.enable80211AC = false; + iface_params.channelParams.enableAcs = false; + iface_params.channelParams.acsShouldExcludeDfs = false; + iface_params.channelParams.channel = kIfaceInvalidChannel; + iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ; + return iface_params; + } + + IHostapd::NetworkParams getPskNwParams() { + IHostapd::NetworkParams nw_params; + nw_params.ssid = + std::vector(kNwSsid, kNwSsid + sizeof(kNwSsid)); + nw_params.isHidden = false; + nw_params.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params.pskPassphrase = kNwPassphrase; + return nw_params; + } + + IHostapd::NetworkParams getInvalidPskNwParams() { + IHostapd::NetworkParams nw_params; + nw_params.ssid = + std::vector(kNwSsid, kNwSsid + sizeof(kNwSsid)); + nw_params.isHidden = false; + nw_params.encryptionType = IHostapd::EncryptionType::WPA2; + return nw_params; + } + + IHostapd::NetworkParams getOpenNwParams() { + IHostapd::NetworkParams nw_params; + nw_params.ssid = + std::vector(kNwSsid, kNwSsid + sizeof(kNwSsid)); + nw_params.isHidden = false; + nw_params.encryptionType = IHostapd::EncryptionType::NONE; + return nw_params; + } + // IHostapd object used for all tests in this fixture. + sp hostapd_; +}; + +/* + * Create: + * Ensures that an instance of the IHostapd proxy object is + * successfully created. + */ +TEST(HostapdHidlTestNoFixture, Create) { + startHostapdAndWaitForHidlService(); + EXPECT_NE(nullptr, getHostapd().get()); + stopHostapd(); +} + +/** + * Adds an access point with PSK network config & ACS enabled. + * Access point creation should pass. + */ +TEST_F(HostapdHidlTest, AddPskAccessPointWithAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(), + getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with Open network config & ACS enabled. + * Access point creation should pass. + */ +TEST_F(HostapdHidlTest, AddOpenAccessPointWithAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(), + getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with PSK network config & ACS disabled. + * Access point creation should pass. + */ +TEST_F(HostapdHidlTest, AddPskAccessPointWithoutAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithoutAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with Open network config & ACS disabled. + * Access point creation should pass. + */ +TEST_F(HostapdHidlTest, AddOpenAccessPointWithoutAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithoutAcs(), getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds & then removes an access point with PSK network config & ACS enabled. + * Access point creation & removal should pass. + */ +TEST_F(HostapdHidlTest, RemoveAccessPointWithAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(), + getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + status = + HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds & then removes an access point with PSK network config & ACS disabled. + * Access point creation & removal should pass. + */ +TEST_F(HostapdHidlTest, RemoveAccessPointWithoutAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithoutAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); + status = + HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid channel. + * Access point creation should fail. + */ +TEST_F(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint, + getIfaceParamsWithInvalidChannel(), getPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid PSK network config. + * Access point creation should fail. + */ +TEST_F(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithoutAcs(), + getInvalidPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp new file mode 100644 index 0000000000..0915150fe5 --- /dev/null +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2016 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 +#include + +#include +#include +#include + +#include +#include + +#include "hostapd_hidl_test_utils.h" +#include "wifi_hidl_test_utils.h" + +using ::android::sp; +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::V1_0::ChipModeId; +using ::android::hardware::wifi::V1_0::IWifiChip; +using ::android::hardware::wifi::hostapd::V1_0::IHostapd; +using ::android::hardware::wifi::hostapd::V1_0::HostapdStatus; +using ::android::hardware::wifi::hostapd::V1_0::HostapdStatusCode; +using ::android::hidl::manager::V1_0::IServiceNotification; +using ::android::wifi_system::HostapdManager; + +namespace { +const char kHostapdServiceName[] = "default"; + +// Helper function to initialize the driver and firmware to AP mode +// using the vendor HAL HIDL interface. +void initilializeDriverAndFirmware() { + sp wifi_chip = getWifiChip(); + ChipModeId mode_id; + EXPECT_TRUE(configureChipToSupportIfaceType( + wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::AP, &mode_id)); +} + +// Helper function to deinitialize the driver and firmware +// using the vendor HAL HIDL interface. +void deInitilializeDriverAndFirmware() { stopWifi(); } +} // namespace + +// Utility class to wait for wpa_hostapd's HIDL service registration. +class ServiceNotificationListener : public IServiceNotification { + public: + Return onRegistration(const hidl_string& fully_qualified_name, + const hidl_string& instance_name, + bool pre_existing) override { + if (pre_existing) { + return Void(); + } + std::unique_lock lock(mutex_); + registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" + + instance_name.c_str()); + lock.unlock(); + condition_.notify_one(); + return Void(); + } + + bool registerForHidlServiceNotifications(const std::string& instance_name) { + if (!IHostapd::registerForNotifications(instance_name, this)) { + return false; + } + configureRpcThreadpool(2, false); + return true; + } + + bool waitForHidlService(uint32_t timeout_in_millis, + const std::string& instance_name) { + std::unique_lock lock(mutex_); + condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis), + [&]() { return registered_.size() >= 1; }); + if (registered_.size() != 1) { + return false; + } + std::string expected_registered = + std::string(IHostapd::descriptor) + "/" + instance_name; + if (registered_[0] != expected_registered) { + LOG(ERROR) << "Expected: " << expected_registered + << ", Got: " << registered_[0]; + return false; + } + return true; + } + + private: + std::vector registered_{}; + std::mutex mutex_; + std::condition_variable condition_; +}; + +void stopHostapd() { + HostapdManager hostapd_manager; + + ASSERT_TRUE(hostapd_manager.StopHostapd()); + deInitilializeDriverAndFirmware(); +} + +void startHostapdAndWaitForHidlService() { + initilializeDriverAndFirmware(); + + android::sp notification_listener = + new ServiceNotificationListener(); + ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications( + kHostapdServiceName)); + + HostapdManager hostapd_manager; + ASSERT_TRUE(hostapd_manager.StartHostapd()); + + ASSERT_TRUE( + notification_listener->waitForHidlService(200, kHostapdServiceName)); +} + +sp getHostapd() { + return ::testing::VtsHalHidlTargetTestBase::getService(); +} diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h new file mode 100644 index 0000000000..74ed28476b --- /dev/null +++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 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 HOSTAPD_HIDL_TEST_UTILS_H +#define HOSTAPD_HIDL_TEST_UTILS_H + +#include + +// Used to stop the android wifi framework before every test. +void stopWifiFramework(); +void startWifiFramework(); +void stopHostapd(); +// Used to configure the chip, driver and start wpa_hostapd before every +// test. +void startHostapdAndWaitForHidlService(); + +// Helper functions to obtain references to the various HIDL interface objects. +// Note: We only have a single instance of each of these objects currently. +// These helper functions should be modified to return vectors if we support +// multiple instances. +android::sp getHostapd(); + +#endif /* HOSTAPD_HIDL_TEST_UTILS_H */