unit-test-app: support passing parameter with signals

This commit is contained in:
He Yin Ling 2018-12-13 16:58:34 +08:00 committed by bot
parent 65d01336d3
commit 783cb692e8
5 changed files with 160 additions and 43 deletions

View file

@ -75,13 +75,27 @@ As the secnario in the above example, slave should get GPIO level after master s
DUT1 (master) console::
Waiting for signal: [output high level]!
Please press "Enter" key to once any board send this signal.
Please press "Enter" key once any board send this signal.
DUT2 (slave) console::
Send signal: [output high level]!
Once the signal is set from DUT2, you need to press "Enter" on DUT1, then DUT1 unblocks from ``unity_wait_for_signal`` and starts to change GPIO level.
Once the signal is sent from DUT2, you need to press "Enter" on DUT1, then DUT1 unblocks from ``unity_wait_for_signal`` and starts to change GPIO level.
Signals can also be used to pass parameters between multiple devices. For example, DUT1 want to know the MAC address of DUT2, so it can connect to DUT2.
In this case, ``unity_wait_for_signal_param`` and ``unity_send_signal_param`` can be used:
DUT1 console::
Waiting for signal: [dut2 mac address]!
Please input parameter value from any board send this signal and press "Enter" key.
DUT2 console::
Send signal: [dut2 mac address][10:20:30:40:50:60]!
Once the signal is sent from DUT2, you need to input ``10:20:30:40:50:60`` on DUT1 and press "Enter". Then DUT1 will get the MAC address string of DUT2 and unblocks from ``unity_wait_for_signal_param``, start to connect to DUT2.
Add multiple stages test cases
@ -165,13 +179,13 @@ Normal case will print the case name and description. Master slave cases will al
Test cases can be run by inputting one of the following:
- Test case name in quotation marks to run a single test case
- Test case name in quotation marks (for example, ``"esp_ota_begin() verifies arguments"``) to run a single test case.
- Test case index to run a single test case
- Test case index (for example, ``1``) to run a single test case.
- Module name in square brackets to run all test cases for a specific module
- Module name in square brackets (for example, ``[cxx]``) to run all test cases for a specific module.
- An asterisk to run all test cases
- An asterisk (``*``) to run all test cases
``[multi_device]`` and ``[multi_stage]`` tags tell the test runner whether a test case is a multiple devices or multiple stages test case.
These tags are automatically added by ```TEST_CASE_MULTIPLE_STAGES`` and ``TEST_CASE_MULTIPLE_DEVICES`` macros.

View file

@ -109,6 +109,21 @@ DUT2slave终端
一旦 DUT2 发送了该信号,您需要在 DUT2 的终端输入回车,然后 DUT1 会从
``unity_wait_for_signal`` 函数中解除阻塞,并开始更改 GPIO 的电平。
信号也可以用来在不同 DUT 之间传递参数。例如DUT1 希望能够拿到 DUT2 的 MAC 地址,来进行蓝牙连接。
这时,我们可以使用 ``unity_wait_for_signal_param`` 以及 ``unity_send_signal_param``
DUT1 终端::
Waiting for signal: [dut2 mac address]!
Please input parameter value from any board send this signal and press "Enter" key.
DUT2 终端::
Send signal: [dut2 mac address][10:20:30:40:50:60]!
一旦 DUT2 发送信号,您需要在 DUT1 输入 ``10:20:30:40:50:60`` 及回车,然后 DUT1 会从 ``unity_wait_for_signal_param`` 中获取到蓝牙地址的字符串,并解除阻塞开始蓝牙连接。
添加多阶段测试用例
------------------
@ -203,13 +218,13 @@ DUT2slave终端
可以输入以下任意一项来运行测试用例:
- 引号中的测试用例的名字,运行单个测试用例。
- 引号中的测试用例的名字(例如 ``"esp_ota_begin() verifies arguments"``,运行单个测试用例。
- 测试用例的序号,运行单个测试用例。
- 测试用例的序号(例如 ``1``,运行单个测试用例。
- 方括号中的模块名字,运行指定模块所有的测试用例。
- 方括号中的模块名字(例如 ``[cxx]``,运行指定模块所有的测试用例。
- 星号,运行所有测试用例。
- 星号 (``*``),运行所有测试用例。
``[multi_device]````[multi_stage]``
标签告诉测试运行者该用例是多设备测试还是多阶段测试。这些标签由

View file

@ -107,9 +107,8 @@ void unity_reset_leak_checks(void);
*/
void test_case_uses_tcpip(void);
/**
* @brief wait for signals.
* @brief wait for signals with parameters.
*
* for multiple devices test cases, DUT might need to wait for other DUTs before continue testing.
* As all DUTs are independent, need user (or test script) interaction to make test synchronized.
@ -136,13 +135,64 @@ void test_case_uses_tcpip(void);
*
* Then we press Enter key on DUT1's console, DUT1 starts to read input and then test success.
*
* Another example, we have 2 DUTs in multiple devices test, and DUT1 need to get DUT2's mac address to perform BT connection.
* DUT1 should call `unity_wait_for_signal_param("dut2 mac address", mac, 19);` to wait for DUT2's mac address.
* DUT2 should call `unity_send_signal_param("dut2 mac address", "10:20:30:40:50:60");` to send to DUT1 its mac address.
* According to the console logs:
*
* DUT1 console:
*
* ```
* Waiting for signal: [dut2 mac address]!
* Please input parameter value from any board send this signal and press "Enter" key.
* ```
*
* DUT2 console:
*
* ```
* Send signal: [dut2 mac address][10:20:30:40:50:60]!
* ```
*
* @param signal_name signal name which DUT expected to wait before proceed testing
* @param parameter_buf buffer to receive parameter
* @param buf_len length of parameter_buf.
* Currently we have a limitation that it will write 1 extra byte at the end of string.
* We need to use a buffer with 2 bytes longer than actual string length.
*/
void unity_wait_for_signal(const char* signal_name);
void unity_wait_for_signal_param(const char* signal_name, char *parameter_buf, uint8_t buf_len);
/**
* @brief DUT send signal.
* @brief wait for signals.
*
* @param signal_name signal name which DUT expected to wait before proceed testing
*/
static inline void unity_wait_for_signal(const char* signal_name)
{
unity_wait_for_signal_param(signal_name, NULL, 0);
}
/**
* @brief DUT send signal and pass parameter to other devices.
*
* @param signal_name signal name which DUT send once it finished preparing.
* @param parameter a string to let remote device to receive.
*/
void unity_send_signal_param(const char* signal_name, const char *parameter);
/**
* @brief DUT send signal with parameter.
*
* @param signal_name signal name which DUT send once it finished preparing.
*/
void unity_send_signal(const char* signal_name);
static inline void unity_send_signal(const char* signal_name)
{
unity_send_signal_param(signal_name, NULL);
}
/**
* @brief convert mac string to mac address
*
* @param mac_str MAC address string with format "xx:xx:xx:xx:xx:xx"
* @param[out] mac_addr store converted MAC address
*/
bool unity_util_convert_mac_from_string(const char* mac_str, uint8_t *mac_addr);

View file

@ -31,20 +31,6 @@ const esp_partition_t *get_test_data_partition()
return result;
}
// wait user to send "Enter" key
static void wait_user_control()
{
char sign[5] = {0};
while(strlen(sign) == 0)
{
/* Flush anything already in the RX buffer */
while(uart_rx_one_char((uint8_t *) sign) == OK) {
}
/* Read line */
UartRxString((uint8_t*) sign, sizeof(sign) - 1);
}
}
void test_case_uses_tcpip()
{
// Can be called more than once, does nothing on subsequent calls
@ -71,16 +57,60 @@ void test_case_uses_tcpip()
unity_reset_leak_checks();
}
// wait user to send "Enter" key or input parameter
static void wait_user_control(char* parameter_buf, uint8_t buf_len)
{
char *buffer = parameter_buf;
char sign[5];
uint8_t buffer_len = buf_len - 1;
if (parameter_buf == NULL) {
buffer = sign;
buffer_len = sizeof(sign) - 1;
}
// workaround that unity_gets (UartRxString) will not set '\0' correctly
bzero(buffer, buffer_len);
unity_gets(buffer, buffer_len);
}
// signal functions, used for sync between unity DUTs for multiple devices cases
void unity_wait_for_signal(const char* signal_name)
void unity_wait_for_signal_param(const char* signal_name, char* parameter_buf, uint8_t buf_len)
{
printf("Waiting for signal: [%s]!\n"
"Please press \"Enter\" key to once any board send this signal.\n", signal_name);
wait_user_control();
printf("Waiting for signal: [%s]!\n", signal_name);
if (parameter_buf == NULL) {
printf("Please press \"Enter\" key once any board send this signal.\n");
} else {
printf("Please input parameter value from any board send this signal and press \"Enter\" key.\n");
}
wait_user_control(parameter_buf, buf_len);
}
void unity_send_signal(const char* signal_name)
void unity_send_signal_param(const char* signal_name, const char *parameter)
{
printf("Send signal: [%s]!\n", signal_name);
if (parameter == NULL) {
printf("Send signal: [%s]!\n", signal_name);
} else {
printf("Send signal: [%s][%s]!\n", signal_name, parameter);
}
}
bool unity_util_convert_mac_from_string(const char* mac_str, uint8_t *mac_addr)
{
uint8_t loop = 0;
uint8_t tmp = 0;
const char *start;
char *stop;
for (loop = 0; loop < 6; loop++) {
start = mac_str + loop * 3;
tmp = strtol(start, &stop, 16);
if (stop - start == 2 && (*stop == ':' || (*stop == 0 && loop == 5))) {
mac_addr[loop] = tmp;
} else {
return false;
}
}
return true;
}

View file

@ -300,8 +300,8 @@ def run_unit_test_cases(env, extra_data):
class Handler(threading.Thread):
WAIT_SIGNAL_PATTERN = re.compile(r'Waiting for signal: \[(.+)\]!')
SEND_SIGNAL_PATTERN = re.compile(r'Send signal: \[(.+)\]!')
WAIT_SIGNAL_PATTERN = re.compile(r'Waiting for signal: \[(.+)]!')
SEND_SIGNAL_PATTERN = re.compile(r'Send signal: \[([^]]+)](\[([^]]+)])?!')
FINISH_PATTERN = re.compile(r"1 Tests (\d) Failures (\d) Ignored")
def __init__(self, dut, sent_signal_list, lock, parent_case_name, child_case_index, timeout):
@ -348,15 +348,23 @@ class Handler(threading.Thread):
Utility.console_log("Timeout in device for function: %s" % self.child_case_name, color="orange")
break
with self.lock:
if expected_signal in self.sent_signal_list:
self.dut.write(" ")
self.sent_signal_list.remove(expected_signal)
break
time.sleep(0.01)
for sent_signal in self.sent_signal_list:
if expected_signal == sent_signal["name"]:
self.dut.write(sent_signal["parameter"])
self.sent_signal_list.remove(sent_signal)
break
else:
time.sleep(0.01)
continue
break
def device_send_action(data):
with self.lock:
self.sent_signal_list.append(data[0].encode('utf-8'))
self.sent_signal_list.append({
"name": data[0].encode('utf-8'),
"parameter": "" if data[2] is None else data[2].encode('utf-8')
# no parameter means we only write EOL to DUT
})
def handle_device_test_finish(data):
""" test finished without reset """