]> granicus.if.org Git - esp-idf/commitdiff
unit-test-app: support passing parameter with signals
authorHe Yin Ling <heyinling@espressif.com>
Thu, 13 Dec 2018 08:58:34 +0000 (16:58 +0800)
committerbot <bot@espressif.com>
Thu, 10 Jan 2019 09:51:17 +0000 (09:51 +0000)
docs/en/api-guides/unit-tests.rst
docs/zh_CN/api-guides/unit-tests.rst
tools/unit-test-app/components/test_utils/include/test_utils.h
tools/unit-test-app/components/test_utils/test_utils.c
tools/unit-test-app/unit_test.py

index b9cfaa39da94b61435c4077a119808ff507c27ce..577bdd588197cd200f16a3e275b5415b618394b1 100644 (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.
index 1e78cd98a7b8e5ce0c1ae06a8c99964b40b6c623..7924fc6bebd5a461c7cac1f8f7fd7cde076bf853 100644 (file)
@@ -109,6 +109,21 @@ DUT2(slave)终端:
 一旦 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 @@ DUT2(slave)终端:
 
 可以输入以下任意一项来运行测试用例:
 
--  引号中的测试用例的名字,运行单个测试用例。
+-  å¼\95å\8f·ä¸­ç\9a\84æµ\8bè¯\95ç\94¨ä¾\8bç\9a\84å\90\8då­\97ï¼\88ä¾\8bå¦\82 ``"esp_ota_begin() verifies arguments"``ï¼\89ï¼\8cè¿\90è¡\8cå\8d\95个æµ\8bè¯\95ç\94¨ä¾\8bã\80\82
 
--  测试用例的序号,运行单个测试用例。
+-  æµ\8bè¯\95ç\94¨ä¾\8bç\9a\84åº\8få\8f·ï¼\88ä¾\8bå¦\82 ``1``ï¼\89ï¼\8cè¿\90è¡\8cå\8d\95个æµ\8bè¯\95ç\94¨ä¾\8bã\80\82
 
--  方括号中的模块名字,运行指定模块所有的测试用例。
+-  æ\96¹æ\8b¬å\8f·ä¸­ç\9a\84模å\9d\97å\90\8då­\97ï¼\88ä¾\8bå¦\82 ``[cxx]``ï¼\89ï¼\8cè¿\90è¡\8cæ\8c\87å®\9a模å\9d\97æ\89\80æ\9c\89ç\9a\84æµ\8bè¯\95ç\94¨ä¾\8bã\80\82
 
--  星号,运行所有测试用例。
+-  星号 (``*``),运行所有测试用例。
 
 ``[multi_device]`` 和 ``[multi_stage]``
 标签告诉测试运行者该用例是多设备测试还是多阶段测试。这些标签由
index a4b7eccb7bf0cf5e1c7d87b7c25a11c0a0dfe339..67c7e0aa47f1eef4730835f4dc31204b11190877 100644 (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);
index 36aae4c291f93685f341e1206a45867dd505e9ba..e42843f76c0411360bc9d3cd99a99fed4da242ad 100644 (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;
 }
 
index 407f97fe44caeeca527df2a9bfff01ba4180a1a6..4f4a8148229583ca27389f8dde97d64886890dad 100755 (executable)
@@ -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 """