diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 2cc9b39d90..01cb606842 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -1069,6 +1069,15 @@ pytest_examples_openthread_br: - esp32c6 - openthread_br +pytest_examples_openthread_sleep: + extends: + - .pytest_examples_dir_template + - .rules:test:example_test-esp32h2 + needs: + - build_pytest_examples_esp32c6 + - build_pytest_examples_esp32h2 + tags: [ esp32c6, openthread_sleep ] + pytest_examples_zigbee: extends: - .pytest_examples_dir_template diff --git a/conftest.py b/conftest.py index 608fae5d43..ca0f0d3795 100644 --- a/conftest.py +++ b/conftest.py @@ -132,6 +132,7 @@ ENV_MARKERS = { # multi-dut markers 'ieee802154': 'ieee802154 related tests should run on ieee802154 runners.', 'openthread_br': 'tests should be used for openthread border router.', + 'openthread_sleep': 'tests should be used for openthread sleepy device.', 'zigbee_multi_dut': 'zigbee runner which have multiple duts.', 'wifi_two_dut': 'tests should be run on runners which has two wifi duts connected.', 'generic_multi_device': 'generic multiple devices whose corresponding gpio pins are connected to each other.', diff --git a/examples/openthread/.build-test-rules.yml b/examples/openthread/.build-test-rules.yml index 708b984373..eb59f014aa 100644 --- a/examples/openthread/.build-test-rules.yml +++ b/examples/openthread/.build-test-rules.yml @@ -3,24 +3,23 @@ # TODO: Modify the configuration after the files matching rules are changed # Or delete TODO without modifying the configuration if it is sure that current rules are correct. .openthread_dependencies: &openthread_dependencies + depends_components: + - esp_coex + - esp_netif + - esp_phy + - ieee802154 + - lwip + - openthread depends_filepatterns: - - components/esp_coex/* - - components/esp_coex/**/* - - components/esp_netif/* - - components/esp_netif/**/* - - components/esp_phy/* - - components/esp_phy/**/* - - components/ieee802154/* - - components/ieee802154/**/* - - components/lwip/* - - components/lwip/**/* - - components/openthread/* - - components/openthread/**/* - examples/common_components/iperf/* - examples/common_components/iperf/**/* - examples/openthread/* - examples/openthread/**/* +.openthread_sleep_dependencies: &openthread_sleep_dependencies + depends_components: + - esp_hw_support + examples/openthread/ot_br: disable: - if: IDF_TARGET in ["esp32h2"] @@ -35,10 +34,6 @@ examples/openthread/ot_br: examples/openthread/ot_cli: enable: - if: IDF_TARGET in ["esp32h2", "esp32c6"] - disable_test: - - if: IDF_TARGET == "esp32c6" - temporary: true - reason: only test on esp32h2 <<: *openthread_dependencies examples/openthread/ot_rcp: @@ -53,8 +48,4 @@ examples/openthread/ot_rcp: examples/openthread/ot_sleepy_device: enable: - if: IDF_TARGET in ["esp32h2", "esp32c6"] - disable_test: - - if: IDF_TARGET in ["esp32h2", "esp32c6"] - temporary: true - reason: No support # TO-DO: TZ-134 - <<: *openthread_dependencies + <<: [*openthread_dependencies, *openthread_sleep_dependencies] diff --git a/examples/openthread/ot_ci_function.py b/examples/openthread/ot_ci_function.py index 6cd68793d1..48db7e60e5 100644 --- a/examples/openthread/ot_ci_function.py +++ b/examples/openthread/ot_ci_function.py @@ -23,6 +23,26 @@ class thread_parameter: self.channel = channel self.exaddr = exaddr self.bbr = bbr + self.networkname = '' + self.panid = '' + self.extpanid = '' + self.networkkey = '' + self.pskc = '' + + def setnetworkname(self, networkname:str) -> None: + self.networkname = networkname + + def setpanid(self, panid:str) -> None: + self.panid = panid + + def setextpanid(self, extpanid:str) -> None: + self.extpanid = extpanid + + def setnetworkkey(self, networkkey:str) -> None: + self.networkkey = networkkey + + def setpskc(self, pskc:str) -> None: + self.pskc = pskc class wifi_parameter: @@ -34,23 +54,43 @@ class wifi_parameter: def joinThreadNetwork(dut:IdfDut, thread:thread_parameter) -> None: - if thread.dataset != '': + if thread.dataset: command = 'dataset set active ' + thread.dataset execute_command(dut, command) dut.expect('Done', timeout=5) else: execute_command(dut, 'dataset init new') dut.expect('Done', timeout=5) - execute_command(dut, 'dataset commit active') - dut.expect('Done', timeout=5) - if thread.channel != '': - command = 'channel ' + thread.channel + if thread.channel: + command = 'dataset channel ' + thread.channel execute_command(dut, command) dut.expect('Done', timeout=5) - if thread.exaddr != '': + if thread.exaddr: command = 'extaddr ' + thread.exaddr execute_command(dut, command) dut.expect('Done', timeout=5) + if thread.networkname: + command = 'dataset networkname ' + thread.networkname + execute_command(dut, command) + dut.expect('Done', timeout=5) + if thread.panid: + command = 'dataset panid ' + thread.panid + execute_command(dut, command) + dut.expect('Done', timeout=5) + if thread.extpanid: + command = 'dataset extpanid ' + thread.extpanid + execute_command(dut, command) + dut.expect('Done', timeout=5) + if thread.networkkey: + command = 'dataset networkkey ' + thread.networkkey + execute_command(dut, command) + dut.expect('Done', timeout=5) + if thread.pskc: + command = 'dataset pskc ' + thread.pskc + execute_command(dut, command) + dut.expect('Done', timeout=5) + execute_command(dut, 'dataset commit active') + dut.expect('Done', timeout=5) if thread.bbr: execute_command(dut, 'bbr enable') dut.expect('Done', timeout=5) @@ -109,9 +149,13 @@ def getDataset(dut:IdfDut) -> str: return str(dut_data) -def reset_thread(dut:IdfDut) -> None: +def init_thread(dut:IdfDut) -> None: dut.expect('>', timeout=10) wait(dut, 3) + reset_thread(dut) + + +def reset_thread(dut:IdfDut) -> None: clean_buffer(dut) execute_command(dut, 'factoryreset') dut.expect('OpenThread attached to netif', timeout=20) diff --git a/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 new file mode 100644 index 0000000000..e61c1118f2 --- /dev/null +++ b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="esp32c6" +CONFIG_IDF_TARGET_ESP32C6=y +CONFIG_OPENTHREAD_NETWORK_CHANNEL=12 +CONFIG_OPENTHREAD_NETWORK_MASTERKEY="aabbccddeeff00112233445566778899" diff --git a/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 new file mode 100644 index 0000000000..fbc855ee78 --- /dev/null +++ b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="esp32h2" +CONFIG_IDF_TARGET_ESP32H2=y +CONFIG_OPENTHREAD_NETWORK_CHANNEL=12 +CONFIG_OPENTHREAD_NETWORK_MASTERKEY="aabbccddeeff00112233445566778899" diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index b90ed95e42..87334b4264 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -91,9 +91,9 @@ def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut]) -> None: cli_list = [cli_h2] router_extaddr_list = ['7766554433221101'] - ocf.reset_thread(br) + ocf.init_thread(br) for cli in cli_list: - ocf.reset_thread(cli) + ocf.init_thread(cli) br_ot_para = default_br_ot_para ocf.joinThreadNetwork(br, br_ot_para) cli_ot_para = default_cli_ot_para @@ -125,8 +125,8 @@ def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut]) -> None: # / \ # Wi-FI_Host Thread_End_Device def formBasicWiFiThreadNetwork(br:IdfDut, cli:IdfDut) -> None: - ocf.reset_thread(br) - ocf.reset_thread(cli) + ocf.init_thread(br) + ocf.init_thread(cli) ocf.joinWiFiNetwork(br, default_br_wifi_para) ocf.joinThreadNetwork(br, default_br_ot_para) ot_para = default_cli_ot_para @@ -540,3 +540,84 @@ def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N ocf.execute_command(cli, 'factoryreset') time.sleep(3) assert b'hello' in mytcp.tcp_bytes + + +# Case 10: Sleepy device test +@pytest.mark.esp32h2 +@pytest.mark.esp32c6 +@pytest.mark.openthread_sleep +@pytest.mark.parametrize( + 'config, count, app_path, target', [ + ('cli_h2|sleepy_c6', 2, + f'{os.path.join(os.path.dirname(__file__), "ot_cli")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device")}', + 'esp32h2|esp32c6'), + ('cli_c6|sleepy_h2', 2, + f'{os.path.join(os.path.dirname(__file__), "ot_cli")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device")}', + 'esp32c6|esp32h2'), + ], + indirect=True, +) +def test_ot_sleepy_device(dut: Tuple[IdfDut, IdfDut]) -> None: + leader = dut[0] + sleepy_device = dut[1] + try: + ocf.init_thread(leader) + time.sleep(3) + leader_para = ocf.thread_parameter('leader', '', '12', '7766554433221100', False) + leader_para.setnetworkname('OpenThread-ESP') + leader_para.setpanid('0x1234') + leader_para.setextpanid('dead00beef00cafe') + leader_para.setnetworkkey('aabbccddeeff00112233445566778899') + leader_para.setpskc('104810e2315100afd6bc9215a6bfac53') + ocf.clean_buffer(sleepy_device) + ocf.joinThreadNetwork(leader, leader_para) + ocf.clean_buffer(sleepy_device) + sleepy_device.serial.hard_reset() + sleepy_device.expect('detached -> child', timeout=20) + ocf.clean_buffer(sleepy_device) + output = sleepy_device.expect(pexpect.TIMEOUT, timeout=5) + assert 'rst:' not in str(output) and 'boot:' not in str(output) + finally: + ocf.execute_command(leader, 'factoryreset') + time.sleep(3) + + +# Case 11: Basic startup Test of BR +@pytest.mark.supported_targets +@pytest.mark.esp32h2 +@pytest.mark.esp32c6 +@pytest.mark.openthread_br +@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.parametrize( + 'config, count, app_path, target', [ + ('rcp|br', 2, + f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', + 'esp32c6|esp32s3'), + ], + indirect=True, +) +def test_basic_startup(dut: Tuple[IdfDut, IdfDut]) -> None: + br = dut[1] + dut[0].serial.stop_redirect_thread() + try: + ocf.init_thread(br) + time.sleep(3) + ocf.clean_buffer(br) + ocf.execute_command(br, 'ifconfig up') + br.expect('Done', timeout=5) + ocf.execute_command(br, 'thread start') + br.expect('Done', timeout=5) + assert ocf.wait_for_join(br, 'leader') + ocf.reset_thread(br) + ocf.joinWiFiNetwork(br, default_br_wifi_para) + ocf.execute_command(br, 'ifconfig up') + br.expect('Done', timeout=5) + ocf.execute_command(br, 'thread start') + br.expect('Done', timeout=5) + assert ocf.wait_for_join(br, 'leader') + finally: + ocf.execute_command(br, 'factoryreset') + time.sleep(3)