pytest_otbr.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  2. # SPDX-License-Identifier: Unlicense OR CC0-1.0
  3. # !/usr/bin/env python3
  4. import os.path
  5. import re
  6. import subprocess
  7. import threading
  8. import time
  9. from typing import Tuple
  10. import ot_ci_function as ocf
  11. import pexpect
  12. import pytest
  13. from pytest_embedded_idf.dut import IdfDut
  14. # This file contains the test scripts for Thread:
  15. # Case 1: Thread network formation and attaching
  16. # A Thread Border Router forms a Thread network, Thread devices attache to it, then test ping connection between them.
  17. # Case 2: Bidirectional IPv6 connectivity
  18. # Test IPv6 ping connection between Thread device and Linux Host (via Thread Border Router).
  19. # Case 3: Multicast forwarding from Wi-Fi to Thread network
  20. # Thread device joins the multicast group, then test group communication from Wi-Fi to Thread network.
  21. # Case 4: Multicast forwarding from Thread to Wi-Fi network
  22. # Linux Host joins the multicast group, test group communication from Thread to Wi-Fi network.
  23. # Case 5: discover Serice published by Thread device
  24. # Thread device publishes the service, Linux Host discovers the service on Wi-Fi network.
  25. # Case 6: discover Serice published by W-Fi device
  26. # Linux Host device publishes the service on Wi-Fi network, Thread device discovers the service.
  27. # Case 7: ICMP communication via NAT64
  28. # Thread device (IPV6) ping the host device (IPV4) via NAT64.
  29. # Case 8: UDP communication via NAT64
  30. # Thread device (IPV6) send udp message to the host device (IPV4) via NAT64.
  31. # Case 9: TCP communication via NAT64
  32. # Thread device (IPV6) send tcp message to the host device (IPV4) via NAT64.
  33. @pytest.fixture(scope='module', name='Init_avahi')
  34. def fixture_Init_avahi() -> bool:
  35. print('Init Avahi')
  36. ocf.start_avahi()
  37. time.sleep(10)
  38. return True
  39. @pytest.fixture(name='Init_interface')
  40. def fixture_Init_interface() -> bool:
  41. print('Init interface')
  42. ocf.init_interface_ipv6_address()
  43. ocf.reset_host_interface()
  44. time.sleep(30)
  45. ocf.set_interface_sysctl_options()
  46. return True
  47. default_br_ot_para = ocf.thread_parameter('leader', '', '12', '7766554433221100', True)
  48. default_br_wifi_para = ocf.wifi_parameter('OTCITE', 'otcitest888', 10)
  49. default_cli_ot_para = ocf.thread_parameter('router', '', '', '', False)
  50. # Case 1: Thread network formation and attaching
  51. @pytest.mark.supported_targets
  52. @pytest.mark.esp32h2
  53. @pytest.mark.esp32c6
  54. @pytest.mark.openthread_br
  55. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  56. @pytest.mark.parametrize(
  57. 'config, count, app_path, target', [
  58. ('rcp|cli_h2|br', 3,
  59. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  60. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  61. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  62. 'esp32c6|esp32h2|esp32s3'),
  63. ],
  64. indirect=True,
  65. )
  66. def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  67. br = dut[2]
  68. cli_h2 = dut[1]
  69. dut[0].serial.stop_redirect_thread()
  70. cli_list = [cli_h2]
  71. router_extaddr_list = ['7766554433221101']
  72. ocf.init_thread(br)
  73. for cli in cli_list:
  74. ocf.init_thread(cli)
  75. br_ot_para = default_br_ot_para
  76. ocf.joinThreadNetwork(br, br_ot_para)
  77. cli_ot_para = default_cli_ot_para
  78. cli_ot_para.dataset = ocf.getDataset(br)
  79. try:
  80. order = 0
  81. for cli in cli_list:
  82. cli_ot_para.exaddr = router_extaddr_list[order]
  83. order = order + 1
  84. ocf.joinThreadNetwork(cli, cli_ot_para)
  85. for cli in cli_list:
  86. cli_mleid_addr = ocf.get_mleid_addr(cli)
  87. br_mleid_addr = ocf.get_mleid_addr(br)
  88. rx_nums = ocf.ot_ping(cli, br_mleid_addr, 5)[1]
  89. assert rx_nums == 5
  90. rx_nums = ocf.ot_ping(br, cli_mleid_addr, 5)[1]
  91. assert rx_nums == 5
  92. finally:
  93. ocf.execute_command(br, 'factoryreset')
  94. for cli in cli_list:
  95. ocf.execute_command(cli, 'factoryreset')
  96. time.sleep(3)
  97. # Form a Wi-Fi/Thread network with a Wi-Fi host, a border router and a Thread end device
  98. # Topology:
  99. # Border_Router
  100. # / \
  101. # / \
  102. # Wi-FI_Host Thread_End_Device
  103. def formBasicWiFiThreadNetwork(br:IdfDut, cli:IdfDut) -> None:
  104. ocf.init_thread(br)
  105. ocf.init_thread(cli)
  106. ocf.joinWiFiNetwork(br, default_br_wifi_para)
  107. ocf.joinThreadNetwork(br, default_br_ot_para)
  108. ot_para = default_cli_ot_para
  109. ot_para.dataset = ocf.getDataset(br)
  110. ot_para.exaddr = '7766554433221101'
  111. ocf.joinThreadNetwork(cli, ot_para)
  112. ocf.wait(cli,10)
  113. # Case 2: Bidirectional IPv6 connectivity
  114. @pytest.mark.supported_targets
  115. @pytest.mark.esp32h2
  116. @pytest.mark.esp32c6
  117. @pytest.mark.openthread_br
  118. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  119. @pytest.mark.parametrize(
  120. 'config, count, app_path, target', [
  121. ('rcp|cli_h2|br', 3,
  122. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  123. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  124. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  125. 'esp32c6|esp32h2|esp32s3'),
  126. ],
  127. indirect=True,
  128. )
  129. def test_Bidirectional_IPv6_connectivity(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  130. br = dut[2]
  131. cli = dut[1]
  132. assert Init_interface
  133. dut[0].serial.stop_redirect_thread()
  134. formBasicWiFiThreadNetwork(br, cli)
  135. try:
  136. assert ocf.is_joined_wifi_network(br)
  137. cli_global_unicast_addr = ocf.get_global_unicast_addr(cli, br)
  138. print('cli_global_unicast_addr', cli_global_unicast_addr)
  139. command = 'ping ' + str(cli_global_unicast_addr) + ' -c 10'
  140. out_str = subprocess.getoutput(command)
  141. print('ping result:\n', str(out_str))
  142. role = re.findall(r' (\d+)%', str(out_str))[0]
  143. assert role != '100'
  144. interface_name = ocf.get_host_interface_name()
  145. command = 'ifconfig ' + interface_name + ' | grep inet6 | grep global'
  146. out_bytes = subprocess.check_output(command, shell=True, timeout=5)
  147. out_str = out_bytes.decode('utf-8')
  148. onlinkprefix = ocf.get_onlinkprefix(br)
  149. host_global_unicast_addr = re.findall(r'\W+(%s(?:\w+:){3}\w+)\W+' % onlinkprefix, str(out_str))
  150. rx_nums = 0
  151. for ip_addr in host_global_unicast_addr:
  152. txrx_nums = ocf.ot_ping(cli, str(ip_addr), 5)
  153. rx_nums = rx_nums + int(txrx_nums[1])
  154. assert rx_nums != 0
  155. finally:
  156. ocf.execute_command(br, 'factoryreset')
  157. ocf.execute_command(cli, 'factoryreset')
  158. time.sleep(3)
  159. # Case 3: Multicast forwarding from Wi-Fi to Thread network
  160. @pytest.mark.supported_targets
  161. @pytest.mark.esp32h2
  162. @pytest.mark.esp32c6
  163. @pytest.mark.openthread_br
  164. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  165. @pytest.mark.parametrize(
  166. 'config, count, app_path, target', [
  167. ('rcp|cli_h2|br', 3,
  168. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  169. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  170. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  171. 'esp32c6|esp32h2|esp32s3'),
  172. ],
  173. indirect=True,
  174. )
  175. def test_multicast_forwarding_A(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  176. br = dut[2]
  177. cli = dut[1]
  178. assert Init_interface
  179. dut[0].serial.stop_redirect_thread()
  180. formBasicWiFiThreadNetwork(br, cli)
  181. try:
  182. assert ocf.is_joined_wifi_network(br)
  183. ocf.execute_command(br, 'bbr')
  184. br.expect('server16', timeout=5)
  185. assert ocf.thread_is_joined_group(cli)
  186. interface_name = ocf.get_host_interface_name()
  187. command = 'ping -I ' + str(interface_name) + ' -t 64 ff04::125 -c 10'
  188. out_str = subprocess.getoutput(command)
  189. print('ping result:\n', str(out_str))
  190. role = re.findall(r' (\d+)%', str(out_str))[0]
  191. assert role != '100'
  192. finally:
  193. ocf.execute_command(br, 'factoryreset')
  194. ocf.execute_command(cli, 'factoryreset')
  195. time.sleep(3)
  196. # Case 4: Multicast forwarding from Thread to Wi-Fi network
  197. @pytest.mark.supported_targets
  198. @pytest.mark.esp32h2
  199. @pytest.mark.esp32c6
  200. @pytest.mark.openthread_br
  201. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  202. @pytest.mark.parametrize(
  203. 'config, count, app_path, target', [
  204. ('rcp|cli_h2|br', 3,
  205. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  206. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  207. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  208. 'esp32c6|esp32h2|esp32s3'),
  209. ],
  210. indirect=True,
  211. )
  212. def test_multicast_forwarding_B(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  213. br = dut[2]
  214. cli = dut[1]
  215. assert Init_interface
  216. dut[0].serial.stop_redirect_thread()
  217. formBasicWiFiThreadNetwork(br, cli)
  218. try:
  219. assert ocf.is_joined_wifi_network(br)
  220. ocf.execute_command(br, 'bbr')
  221. br.expect('server16', timeout=5)
  222. ocf.execute_command(cli, 'udp open')
  223. cli.expect('Done', timeout=5)
  224. ocf.wait(cli, 3)
  225. myudp = ocf.udp_parameter('INET6', '::', 5090, 'ff04::125', False, 15.0, b'')
  226. udp_mission = threading.Thread(target=ocf.create_host_udp_server, args=(myudp, ))
  227. udp_mission.start()
  228. start_time = time.time()
  229. while not myudp.init_flag:
  230. if (time.time() - start_time) > 10:
  231. assert False
  232. for num in range(0, 3):
  233. command = 'udp send ff04::125 5090 hello' + str(num)
  234. ocf.execute_command(cli, command)
  235. cli.expect('Done', timeout=5)
  236. ocf.wait(cli, 0.5)
  237. while udp_mission.is_alive():
  238. time.sleep(1)
  239. finally:
  240. ocf.execute_command(br, 'factoryreset')
  241. ocf.execute_command(cli, 'factoryreset')
  242. time.sleep(3)
  243. assert b'hello' in myudp.udp_bytes
  244. # Case 5: discover dervice published by Thread device
  245. @pytest.mark.supported_targets
  246. @pytest.mark.esp32h2
  247. @pytest.mark.esp32c6
  248. @pytest.mark.openthread_br
  249. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  250. @pytest.mark.parametrize(
  251. 'config, count, app_path, target', [
  252. ('rcp|cli_h2|br', 3,
  253. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  254. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  255. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  256. 'esp32c6|esp32h2|esp32s3'),
  257. ],
  258. indirect=True,
  259. )
  260. def test_service_discovery_of_Thread_device(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  261. br = dut[2]
  262. cli = dut[1]
  263. assert Init_interface
  264. assert Init_avahi
  265. dut[0].serial.stop_redirect_thread()
  266. formBasicWiFiThreadNetwork(br, cli)
  267. try:
  268. assert ocf.is_joined_wifi_network(br)
  269. command = 'avahi-browse -rt _testyyy._udp'
  270. out_str = subprocess.getoutput(command)
  271. print('avahi-browse:\n', str(out_str))
  272. assert 'myTest' not in str(out_str)
  273. hostname = 'myTest'
  274. command = 'srp client host name ' + hostname
  275. ocf.execute_command(cli, command)
  276. cli.expect('Done', timeout=5)
  277. cli_global_unicast_addr = ocf.get_global_unicast_addr(cli, br)
  278. print('cli_global_unicast_addr', cli_global_unicast_addr)
  279. command = 'srp client host address ' + str(cli_global_unicast_addr)
  280. ocf.execute_command(cli, command)
  281. cli.expect('Done', timeout=5)
  282. port = '12348'
  283. command = 'srp client service add my-service _testyyy._udp ' + port
  284. ocf.execute_command(cli, command)
  285. cli.expect('Done', timeout=5)
  286. ocf.execute_command(cli, 'srp client autostart enable')
  287. cli.expect('Done', timeout=5)
  288. ocf.wait(cli, 3)
  289. command = 'avahi-browse -rt _testyyy._udp'
  290. out_str = subprocess.getoutput(command)
  291. print('avahi-browse:\n', str(out_str))
  292. assert 'myTest' in str(out_str)
  293. finally:
  294. ocf.execute_command(br, 'factoryreset')
  295. ocf.execute_command(cli, 'factoryreset')
  296. time.sleep(3)
  297. # Case 6: discover dervice published by Wi-Fi device
  298. @pytest.mark.supported_targets
  299. @pytest.mark.esp32h2
  300. @pytest.mark.esp32c6
  301. @pytest.mark.openthread_br
  302. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  303. @pytest.mark.parametrize(
  304. 'config, count, app_path, target', [
  305. ('rcp|cli_h2|br', 3,
  306. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  307. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  308. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  309. 'esp32c6|esp32h2|esp32s3'),
  310. ],
  311. indirect=True,
  312. )
  313. def test_service_discovery_of_WiFi_device(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  314. br = dut[2]
  315. cli = dut[1]
  316. assert Init_interface
  317. assert Init_avahi
  318. dut[0].serial.stop_redirect_thread()
  319. formBasicWiFiThreadNetwork(br, cli)
  320. try:
  321. assert ocf.is_joined_wifi_network(br)
  322. br_global_unicast_addr = ocf.get_global_unicast_addr(br, br)
  323. command = 'dns config ' + br_global_unicast_addr
  324. ocf.execute_command(cli, command)
  325. cli.expect('Done', timeout=5)
  326. ocf.wait(cli, 1)
  327. domain_name = ocf.get_domain()
  328. print('domain name is: ', domain_name)
  329. command = 'dns resolve ' + domain_name + '.default.service.arpa.'
  330. ocf.execute_command(cli, command)
  331. cli.expect('TTL', timeout=10)
  332. cli.expect('Done', timeout=10)
  333. command = 'dns browse _testxxx._udp.default.service.arpa'
  334. tmp = ocf.get_ouput_string(cli, command, 5)
  335. assert 'Port:12347' not in str(tmp)
  336. ocf.host_publish_service()
  337. ocf.wait(cli, 5)
  338. command = 'dns browse _testxxx._udp.default.service.arpa'
  339. tmp = ocf.get_ouput_string(cli, command, 5)
  340. assert 'response for _testxxx' in str(tmp)
  341. assert 'Port:12347' in str(tmp)
  342. command = 'dns browse _testxxx._udp.default.service.arpa'
  343. tmp = ocf.get_ouput_string(cli, command, 5)
  344. ocf.execute_command(cli, 'dns service testxxx _testxxx._udp.default.service.arpa.')
  345. tmp = cli.expect(pexpect.TIMEOUT, timeout=5)
  346. assert 'response for testxxx' in str(tmp)
  347. assert 'Port:12347' in str(tmp)
  348. finally:
  349. ocf.host_close_service()
  350. ocf.execute_command(br, 'factoryreset')
  351. ocf.execute_command(cli, 'factoryreset')
  352. time.sleep(3)
  353. # Case 7: ICMP communication via NAT64
  354. @pytest.mark.supported_targets
  355. @pytest.mark.esp32h2
  356. @pytest.mark.esp32c6
  357. @pytest.mark.openthread_br
  358. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  359. @pytest.mark.parametrize(
  360. 'config, count, app_path, target', [
  361. ('rcp|cli_h2|br', 3,
  362. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  363. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  364. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  365. 'esp32c6|esp32h2|esp32s3'),
  366. ],
  367. indirect=True,
  368. )
  369. def test_ICMP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  370. br = dut[2]
  371. cli = dut[1]
  372. assert Init_interface
  373. dut[0].serial.stop_redirect_thread()
  374. formBasicWiFiThreadNetwork(br, cli)
  375. try:
  376. assert ocf.is_joined_wifi_network(br)
  377. host_ipv4_address = ocf.get_host_ipv4_address()
  378. print('host_ipv4_address: ', host_ipv4_address)
  379. rx_nums = ocf.ot_ping(cli, str(host_ipv4_address), 5)[1]
  380. assert rx_nums != 0
  381. finally:
  382. ocf.execute_command(br, 'factoryreset')
  383. ocf.execute_command(cli, 'factoryreset')
  384. time.sleep(3)
  385. # Case 8: UDP communication via NAT64
  386. @pytest.mark.supported_targets
  387. @pytest.mark.esp32h2
  388. @pytest.mark.esp32c6
  389. @pytest.mark.openthread_br
  390. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  391. @pytest.mark.parametrize(
  392. 'config, count, app_path, target', [
  393. ('rcp|cli_h2|br', 3,
  394. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  395. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  396. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  397. 'esp32c6|esp32h2|esp32s3'),
  398. ],
  399. indirect=True,
  400. )
  401. def test_UDP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  402. br = dut[2]
  403. cli = dut[1]
  404. assert Init_interface
  405. dut[0].serial.stop_redirect_thread()
  406. formBasicWiFiThreadNetwork(br, cli)
  407. try:
  408. assert ocf.is_joined_wifi_network(br)
  409. ocf.execute_command(br, 'bbr')
  410. br.expect('server16', timeout=5)
  411. ocf.execute_command(cli, 'udp open')
  412. cli.expect('Done', timeout=5)
  413. ocf.wait(cli, 3)
  414. host_ipv4_address = ocf.get_host_ipv4_address()
  415. print('host_ipv4_address: ', host_ipv4_address)
  416. myudp = ocf.udp_parameter('INET4', host_ipv4_address, 5090, '', False, 15.0, b'')
  417. udp_mission = threading.Thread(target=ocf.create_host_udp_server, args=(myudp, ))
  418. udp_mission.start()
  419. start_time = time.time()
  420. while not myudp.init_flag:
  421. if (time.time() - start_time) > 10:
  422. assert False
  423. for num in range(0, 3):
  424. command = 'udp send ' + host_ipv4_address + ' 5090 hello' + str(num)
  425. ocf.execute_command(cli, command)
  426. cli.expect('Done', timeout=5)
  427. ocf.wait(cli, 0.5)
  428. while udp_mission.is_alive():
  429. time.sleep(1)
  430. finally:
  431. ocf.execute_command(br, 'factoryreset')
  432. ocf.execute_command(cli, 'factoryreset')
  433. time.sleep(3)
  434. assert b'hello' in myudp.udp_bytes
  435. # Case 9: TCP communication via NAT64
  436. @pytest.mark.supported_targets
  437. @pytest.mark.esp32h2
  438. @pytest.mark.esp32c6
  439. @pytest.mark.openthread_br
  440. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  441. @pytest.mark.parametrize(
  442. 'config, count, app_path, target', [
  443. ('rcp|cli_h2|br', 3,
  444. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  445. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  446. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  447. 'esp32c6|esp32h2|esp32s3'),
  448. ],
  449. indirect=True,
  450. )
  451. def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  452. br = dut[2]
  453. cli = dut[1]
  454. assert Init_interface
  455. dut[0].serial.stop_redirect_thread()
  456. formBasicWiFiThreadNetwork(br, cli)
  457. try:
  458. assert ocf.is_joined_wifi_network(br)
  459. ocf.execute_command(br, 'bbr')
  460. br.expect('server16', timeout=5)
  461. ocf.execute_command(cli, 'tcpsockclient open')
  462. cli.expect('Done', timeout=5)
  463. ocf.wait(cli, 3)
  464. host_ipv4_address = ocf.get_host_ipv4_address()
  465. connect_address = ocf.get_ipv6_from_ipv4(host_ipv4_address, br)
  466. print('connect_address is: ', connect_address)
  467. mytcp = ocf.tcp_parameter('INET4', host_ipv4_address, 12345, False, False, 15.0, b'')
  468. tcp_mission = threading.Thread(target=ocf.create_host_tcp_server, args=(mytcp, ))
  469. tcp_mission.start()
  470. start_time = time.time()
  471. while not mytcp.listen_flag:
  472. if (time.time() - start_time) > 10:
  473. assert False
  474. command = 'tcpsockclient connect ' + connect_address + ' 12345'
  475. ocf.execute_command(cli, command)
  476. cli.expect('Successfully connected', timeout=10)
  477. start_time = time.time()
  478. while not mytcp.recv_flag:
  479. if (time.time() - start_time) > 10:
  480. assert False
  481. command = 'tcpsockclient send hello'
  482. ocf.execute_command(cli, command)
  483. cli.expect('Done', timeout=5)
  484. while tcp_mission.is_alive():
  485. time.sleep(1)
  486. finally:
  487. ocf.execute_command(br, 'factoryreset')
  488. ocf.execute_command(cli, 'factoryreset')
  489. time.sleep(3)
  490. assert b'hello' in mytcp.tcp_bytes
  491. # Case 10: Sleepy device test
  492. @pytest.mark.esp32h2
  493. @pytest.mark.esp32c6
  494. @pytest.mark.openthread_sleep
  495. @pytest.mark.parametrize(
  496. 'config, count, app_path, target', [
  497. ('cli_h2|sleepy_c6', 2,
  498. f'{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  499. f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device")}',
  500. 'esp32h2|esp32c6'),
  501. ('cli_c6|sleepy_h2', 2,
  502. f'{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  503. f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device")}',
  504. 'esp32c6|esp32h2'),
  505. ],
  506. indirect=True,
  507. )
  508. def test_ot_sleepy_device(dut: Tuple[IdfDut, IdfDut]) -> None:
  509. leader = dut[0]
  510. sleepy_device = dut[1]
  511. try:
  512. ocf.init_thread(leader)
  513. time.sleep(3)
  514. leader_para = ocf.thread_parameter('leader', '', '12', '7766554433221100', False)
  515. leader_para.setnetworkname('OpenThread-ESP')
  516. leader_para.setpanid('0x1234')
  517. leader_para.setextpanid('dead00beef00cafe')
  518. leader_para.setnetworkkey('aabbccddeeff00112233445566778899')
  519. leader_para.setpskc('104810e2315100afd6bc9215a6bfac53')
  520. ocf.clean_buffer(sleepy_device)
  521. ocf.joinThreadNetwork(leader, leader_para)
  522. ocf.clean_buffer(sleepy_device)
  523. sleepy_device.serial.hard_reset()
  524. sleepy_device.expect('detached -> child', timeout=20)
  525. sleepy_device.expect('PMU_SLEEP_PD_TOP: True', timeout=10)
  526. sleepy_device.expect('PMU_SLEEP_PD_MODEM: True', timeout=20)
  527. ocf.clean_buffer(sleepy_device)
  528. output = sleepy_device.expect(pexpect.TIMEOUT, timeout=5)
  529. assert 'rst:' not in str(output) and 'boot:' not in str(output)
  530. finally:
  531. ocf.execute_command(leader, 'factoryreset')
  532. time.sleep(3)
  533. # Case 11: Basic startup Test of BR
  534. @pytest.mark.supported_targets
  535. @pytest.mark.esp32h2
  536. @pytest.mark.esp32c6
  537. @pytest.mark.openthread_br
  538. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  539. @pytest.mark.parametrize(
  540. 'config, count, app_path, target', [
  541. ('rcp|br', 2,
  542. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  543. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  544. 'esp32c6|esp32s3'),
  545. ],
  546. indirect=True,
  547. )
  548. def test_basic_startup(dut: Tuple[IdfDut, IdfDut]) -> None:
  549. br = dut[1]
  550. dut[0].serial.stop_redirect_thread()
  551. try:
  552. ocf.init_thread(br)
  553. time.sleep(3)
  554. ocf.clean_buffer(br)
  555. ocf.execute_command(br, 'ifconfig up')
  556. br.expect('Done', timeout=5)
  557. ocf.execute_command(br, 'thread start')
  558. br.expect('Done', timeout=5)
  559. assert ocf.wait_for_join(br, 'leader')
  560. ocf.reset_thread(br)
  561. ocf.joinWiFiNetwork(br, default_br_wifi_para)
  562. ocf.execute_command(br, 'ifconfig up')
  563. br.expect('Done', timeout=5)
  564. ocf.execute_command(br, 'thread start')
  565. br.expect('Done', timeout=5)
  566. assert ocf.wait_for_join(br, 'leader')
  567. finally:
  568. ocf.execute_command(br, 'factoryreset')
  569. time.sleep(3)