mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #12240 from yarbcy/pr/add-new-tests-softap-2
Cypress: Initial commit of SoftAP host testspull/12213/head
commit
c27e644b96
|
@ -0,0 +1,231 @@
|
||||||
|
"""
|
||||||
|
Copyright (c) 2011-2020 ARM Limited
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from mbed_host_tests import BaseHostTest
|
||||||
|
from mbed_host_tests.host_tests_logger import HtrunLogger
|
||||||
|
import platform
|
||||||
|
import time, re, os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
class SoftAPBasicHostTests(BaseHostTest):
|
||||||
|
""" Basic SoftAP test with host as STA
|
||||||
|
|
||||||
|
[Following configuration is required before test]
|
||||||
|
1. Identify and update the host wifi device name self.wifi_dev
|
||||||
|
2. Add user as sudoer without password to allow script to run sudo command. Restrict the sudo command pattern to enhance security
|
||||||
|
### sudoer config begin ###
|
||||||
|
# Allow members of group sudo to execute any command
|
||||||
|
%sudo ALL=(ALL:ALL) ALL
|
||||||
|
<user> ALL=(ALL) NOPASSWD: /usr/sbin/rfkill unblock wifi, /sbin/wpa_supplicant -B -i * -c *, /usr/bin/killall wpa_supplicant, /sbin/wpa_cli -i * status, /sbin/dhclient -r *, /sbin/dhclient -nw -1 *
|
||||||
|
### sudoer config end ###
|
||||||
|
|
||||||
|
[Test behavior]
|
||||||
|
1. Host wait for DUT SoftAP to start
|
||||||
|
2. Upon receive ('softap', 'xxx') message from DUT SoftAP to perform corresponding test
|
||||||
|
"""
|
||||||
|
# Class constants
|
||||||
|
HOST_WIFI_CONNECTION_WAIT_SEC = 8
|
||||||
|
HOST_WIFI_DHCP_GET_IP_WAIT_SEC = 3
|
||||||
|
HOST_WIFI_INTER_CMDS_WAIT_SEC = 1
|
||||||
|
HOST_WIFI_SEND_PING_ECHO_CNT = 1
|
||||||
|
HOST_WPA_STATUS_REGEX = re.compile("^wpa_state=(\w+)$", re.MULTILINE)
|
||||||
|
HOST_WPA_SSID_REGEX = re.compile("^ssid=(\w+)$", re.MULTILINE)
|
||||||
|
HOST_PING_SOFTAP_REGEX = re.compile("^(\d+) packets transmitted, (\d+) received", re.MULTILINE)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(SoftAPBasicHostTests, self).__init__()
|
||||||
|
self.logger = HtrunLogger('TEST')
|
||||||
|
self.log = self.logger.prn_inf
|
||||||
|
|
||||||
|
self.__result = False
|
||||||
|
self.wifi_dev = 'wlan0'
|
||||||
|
|
||||||
|
# The SoftAP config must be consisten with client side
|
||||||
|
self.softap_ssid = 'MBEDSoftAPTest'
|
||||||
|
self.softap_password = 'abcd1234'
|
||||||
|
self.softap_ip_address = '192.168.10.1'
|
||||||
|
|
||||||
|
self.softap_event_action_table = {
|
||||||
|
'up' : self.host_wifi_softap_up_test
|
||||||
|
}
|
||||||
|
|
||||||
|
def _callback_os_type(self, key, value, timestamp):
|
||||||
|
''' Get host OS type
|
||||||
|
'''
|
||||||
|
system_name = platform.system()
|
||||||
|
self.log('os_type = {}'.format(system_name))
|
||||||
|
self.send_kv("os_type", system_name)
|
||||||
|
self.__result = True
|
||||||
|
|
||||||
|
def _callback_softap_events(self, key, value, timestamp):
|
||||||
|
''' DUT SoftAP event handler
|
||||||
|
Root handler of all 'softap' events, dispatch secondary handler based on "value"
|
||||||
|
'''
|
||||||
|
self.log('Get ({}, {}) from DUT'.format(key, value))
|
||||||
|
|
||||||
|
if not value in self.softap_event_action_table:
|
||||||
|
self.log('Unknown softap event {}'.format(value))
|
||||||
|
self.report_error('Unknow softap event')
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not self.softap_event_action_table[value]():
|
||||||
|
self.report_error('Response to ({}, {}) FAILED!'.format(key, value))
|
||||||
|
else:
|
||||||
|
self.report_success()
|
||||||
|
self.__result = True
|
||||||
|
return None
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
# all functions that can be called from the client
|
||||||
|
self.register_callback('softap', self._callback_softap_events)
|
||||||
|
self.register_callback('get_os_type', self._callback_os_type)
|
||||||
|
try:
|
||||||
|
cmd = ['sudo', 'rfkill', 'unblock', 'wifi']
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
self.log('SETUP: {} => {}'.format(cmd, output))
|
||||||
|
time.sleep(SoftAPBasicHostTests.HOST_WIFI_INTER_CMDS_WAIT_SEC)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
self.log ('WARNING: Setup commands may not all scceeed.')
|
||||||
|
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
return self.__result
|
||||||
|
|
||||||
|
def teardown(self):
|
||||||
|
# release existing dhclient
|
||||||
|
try:
|
||||||
|
cmd = ['sudo', 'dhclient', '-r', self.wifi_dev]
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
self.log('TEARDOWN: {} => {}'.format(cmd, output))
|
||||||
|
time.sleep(SoftAPBasicHostTests.HOST_WIFI_INTER_CMDS_WAIT_SEC)
|
||||||
|
|
||||||
|
cmd = ['sudo', 'killall', 'wpa_supplicant']
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
self.log('TEARDOWN: {} => {}'.format(cmd, output))
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
self.log ('WARNING: TearDown commands may not all scceeed.')
|
||||||
|
|
||||||
|
def host_wifi_softap_up_test(self):
|
||||||
|
''' Run host side test for ('softap', 'up') event
|
||||||
|
'''
|
||||||
|
if not self.host_wifi_connect_softap_linux():
|
||||||
|
return False
|
||||||
|
if not self.host_wifi_restart_dhcp_linux():
|
||||||
|
return False
|
||||||
|
if not self.host_wifi_ping_softap():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def host_wifi_connect_softap_linux(self):
|
||||||
|
''' Host Linux as STA to connect to DUT SoftAP
|
||||||
|
Test will run after receiving ('softap', 'up') message from DUT SoftAP
|
||||||
|
'''
|
||||||
|
# killall is expected to fail when the host does NOT run wpa_supplicant by default
|
||||||
|
try:
|
||||||
|
cmd = ['sudo', 'killall', 'wpa_supplicant']
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
self.log('kill existing wpa_supplicant: {}'.format(cmd, universal_newlines=True))
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
self.log('INFO: no prior wpa_supplicant found')
|
||||||
|
|
||||||
|
try:
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
time.sleep(SoftAPBasicHostTests.HOST_WIFI_INTER_CMDS_WAIT_SEC)
|
||||||
|
cmd = ['sudo', 'wpa_supplicant', '-B', '-i', self.wifi_dev, '-c', \
|
||||||
|
dir_path+'/softap_wpa_supplicant.conf']
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
self.log('start wpa_supplicant: {} => {}'.format(cmd, output))
|
||||||
|
|
||||||
|
self.log('Wait {} sec to connecct to {} ...'.format(\
|
||||||
|
SoftAPBasicHostTests.HOST_WIFI_CONNECTION_WAIT_SEC, self.softap_ssid))
|
||||||
|
time.sleep(SoftAPBasicHostTests.HOST_WIFI_CONNECTION_WAIT_SEC)
|
||||||
|
cmd = ['sudo', 'wpa_cli', '-i', self.wifi_dev, 'status']
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
self.log('{}: {}'.format(cmd, output))
|
||||||
|
except subprocess.CalledProcessError as error:
|
||||||
|
self.log("ERROR: {} => {}".format(error.cmd, error.output))
|
||||||
|
return False
|
||||||
|
|
||||||
|
match = SoftAPBasicHostTests.HOST_WPA_STATUS_REGEX.search(output)
|
||||||
|
if match is None or (match.group(1) != 'COMPLETED' and match.group(1) != 'ASSOCIATED'):
|
||||||
|
self.log('ERROR: status => {}'.format(output))
|
||||||
|
return False
|
||||||
|
|
||||||
|
match = SoftAPBasicHostTests.HOST_WPA_SSID_REGEX.search(output)
|
||||||
|
if match is None or match.group(1) != self.softap_ssid:
|
||||||
|
self.log('ERROR: status => {}'.format(output))
|
||||||
|
return False
|
||||||
|
self.log('SoftAP join PASS')
|
||||||
|
return True
|
||||||
|
|
||||||
|
def host_wifi_restart_dhcp_linux(self):
|
||||||
|
''' Restart host dhcp client to obtain IP
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
# release existing dhclient
|
||||||
|
cmd = ['sudo', 'dhclient', '-r', self.wifi_dev]
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
self.log('{} => {}'.format(cmd, output))
|
||||||
|
time.sleep(SoftAPBasicHostTests.HOST_WIFI_INTER_CMDS_WAIT_SEC)
|
||||||
|
|
||||||
|
cmd = ['sudo', 'dhclient', '-nw', '-1', self.wifi_dev]
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
self.log('{} => {}'.format(cmd, output))
|
||||||
|
self.log('Wait {} sec for dhcp to get IP from SoftAP'.format( \
|
||||||
|
SoftAPBasicHostTests.HOST_WIFI_DHCP_GET_IP_WAIT_SEC))
|
||||||
|
time.sleep(SoftAPBasicHostTests.HOST_WIFI_DHCP_GET_IP_WAIT_SEC)
|
||||||
|
except subprocess.CalledProcessError as error:
|
||||||
|
self.log("ERROR: {} => {}".format(error.cmd, error.output))
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def host_wifi_ping_softap(self):
|
||||||
|
''' Ping SoftAP with self.softap_ip_address
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
cmd = ['ping', '-c', str(SoftAPBasicHostTests.HOST_WIFI_SEND_PING_ECHO_CNT), \
|
||||||
|
self.softap_ip_address]
|
||||||
|
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
self.log('{} => {}'.format(cmd, output))
|
||||||
|
except subprocess.CalledProcessError as error:
|
||||||
|
self.log("ERROR: {} => {}".format(error.cmd, error.output))
|
||||||
|
return False
|
||||||
|
|
||||||
|
match = SoftAPBasicHostTests.HOST_PING_SOFTAP_REGEX.search(output)
|
||||||
|
if match is None or match.group(2) == '0':
|
||||||
|
self.log('Ping ERROR: {} => {}'.format(cmd, output))
|
||||||
|
return False
|
||||||
|
self.log('Ping PASS: {}/{} echo received'.format(match.group(2), match.group(1)))
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_wpa_supplicant_conf_path(self):
|
||||||
|
''' Report host side test success to DUT
|
||||||
|
'''
|
||||||
|
self.send_kv("passed", "0")
|
||||||
|
|
||||||
|
def report_success(self):
|
||||||
|
''' Report host side test success to DUT
|
||||||
|
'''
|
||||||
|
self.send_kv("passed", "0")
|
||||||
|
|
||||||
|
def report_error(self, msg):
|
||||||
|
''' Report host side test error to DUT
|
||||||
|
'''
|
||||||
|
self.log('{} failed !!!'.format(msg))
|
||||||
|
self.send_kv("failed", "0")
|
|
@ -0,0 +1,8 @@
|
||||||
|
ctrl_interface=/run/wpa_supplicant
|
||||||
|
update_config=1
|
||||||
|
|
||||||
|
network={
|
||||||
|
ssid="MBEDSoftAPTest"
|
||||||
|
#psk="abcd1234"
|
||||||
|
psk=a2a7f7f2d84390b6c6ba644a3b5f5fbe2113c18734dd992dc0d976529ba684c4
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2019, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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 !defined(MBED_CONF_APP_SOFTAP_SSID) || \
|
||||||
|
!defined(MBED_CONF_APP_SOFTAP_CHANNEL) || \
|
||||||
|
!defined(MBED_CONF_APP_SOFTAP_PASSWORD)
|
||||||
|
|
||||||
|
#error [NOT_SUPPORTED] Requires parameters from mbed_app.json
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SOFTAP 1
|
||||||
|
|
||||||
|
#if MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE != SOFTAP
|
||||||
|
|
||||||
|
#error [NOT_SUPPORTED] SoftAP testing need to be enabled
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(TARGET_PSOC6)
|
||||||
|
#error [NOT_SUPPORTED] Wifi tests are not valid for the target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SOFTAP_IP_ADDRESS "192.168.10.1"
|
||||||
|
#define NETMASK "255.255.255.0"
|
||||||
|
#define GATEWAY "192.168.10.1"
|
||||||
|
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
#include "WhdSoftAPInterface.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
static char _key[256] = { 0 };
|
||||||
|
static char _value[128] = { 0 };
|
||||||
|
|
||||||
|
void host_os_type_verification() {
|
||||||
|
greentea_send_kv("get_os_type", "host");
|
||||||
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
||||||
|
TEST_ASSERT_EQUAL_STRING("Linux", _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void softap_test() {
|
||||||
|
WhdSoftAPInterface *softap = WhdSoftAPInterface::get_default_instance();
|
||||||
|
TEST_ASSERT_TRUE(softap != NULL);
|
||||||
|
|
||||||
|
softap->set_network(SOFTAP_IP_ADDRESS, NETMASK, GATEWAY);
|
||||||
|
int ret = softap->start(MBED_CONF_APP_SOFTAP_SSID, MBED_CONF_APP_SOFTAP_PASSWORD, NSAPI_SECURITY_WPA_WPA2,
|
||||||
|
MBED_CONF_APP_SOFTAP_CHANNEL);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, ret);
|
||||||
|
greentea_send_kv("softap", "up");
|
||||||
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
||||||
|
TEST_ASSERT_EQUAL_STRING("passed", _key);
|
||||||
|
}
|
||||||
|
|
||||||
|
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||||
|
// here, we specify the timeout (150) and the host runner (the name of our Python file)
|
||||||
|
GREENTEA_SETUP(150, "softap_basic");
|
||||||
|
return greentea_test_setup_handler(number_of_cases);
|
||||||
|
}
|
||||||
|
|
||||||
|
Case cases[] = {
|
||||||
|
Case("Host OS Type Verification", host_os_type_verification),
|
||||||
|
Case("SoftAP test", softap_test)
|
||||||
|
};
|
||||||
|
|
||||||
|
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return Harness::run(specification);
|
||||||
|
}
|
Loading…
Reference in New Issue