pytest_otbr.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  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', '', '12', '', False)
  50. # Case 1: Thread network formation and attaching
  51. @pytest.mark.esp32s3
  52. @pytest.mark.esp32h2
  53. @pytest.mark.esp32h4
  54. @pytest.mark.esp32c6
  55. @pytest.mark.openthread_br
  56. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  57. @pytest.mark.parametrize(
  58. 'port, config, count, app_path, beta_target, target', [
  59. ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR|/dev/USB_CLI_C6|/dev/USB_CLI_H2',
  60. 'rcp|cli|br|cli_c6|cli_h2', 5,
  61. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  62. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  63. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}'
  64. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  65. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}',
  66. 'esp32h2beta2|esp32h2beta2|esp32s3|esp32c6|esp32h2',
  67. 'esp32h4|esp32h4|esp32s3|esp32c6|esp32h2'),
  68. ],
  69. indirect=True,
  70. )
  71. def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut, IdfDut, IdfDut]) -> None:
  72. br = dut[2]
  73. cli_h4 = dut[1]
  74. cli_c6 = dut[3]
  75. cli_h2 = dut[4]
  76. dut[0].serial.stop_redirect_thread()
  77. cli_list = [cli_h4, cli_c6, cli_h2]
  78. router_extaddr_list = ['7766554433221101', '7766554433221102', '7766554433221103']
  79. ocf.reset_thread(br)
  80. for cli in cli_list:
  81. ocf.reset_thread(cli)
  82. br_ot_para = default_br_ot_para
  83. ocf.joinThreadNetwork(br, br_ot_para)
  84. cli_ot_para = default_cli_ot_para
  85. cli_ot_para.dataset = ocf.getDataset(br)
  86. try:
  87. order = 0
  88. for cli in cli_list:
  89. cli_ot_para.exaddr = router_extaddr_list[order]
  90. order = order + 1
  91. ocf.joinThreadNetwork(cli, cli_ot_para)
  92. for cli in cli_list:
  93. cli_mleid_addr = ocf.get_mleid_addr(cli)
  94. br_mleid_addr = ocf.get_mleid_addr(br)
  95. rx_nums = ocf.ot_ping(cli, br_mleid_addr, 5)[1]
  96. assert rx_nums == 5
  97. rx_nums = ocf.ot_ping(br, cli_mleid_addr, 5)[1]
  98. assert rx_nums == 5
  99. finally:
  100. br.write('factoryreset')
  101. for cli in cli_list:
  102. cli.write('factoryreset')
  103. time.sleep(3)
  104. # Form a Wi-Fi/Thread network with a Wi-Fi host, a border router and a Thread end device
  105. # Topology:
  106. # Border_Router
  107. # / \
  108. # / \
  109. # Wi-FI_Host Thread_End_Device
  110. def formBasicWiFiThreadNetwork(br:IdfDut, cli:IdfDut) -> None:
  111. ocf.reset_thread(br)
  112. ocf.reset_thread(cli)
  113. ocf.joinWiFiNetwork(br, default_br_wifi_para)
  114. ocf.joinThreadNetwork(br, default_br_ot_para)
  115. ot_para = default_cli_ot_para
  116. ot_para.dataset = ocf.getDataset(br)
  117. ot_para.exaddr = '7766554433221101'
  118. ocf.joinThreadNetwork(cli, ot_para)
  119. ocf.wait(cli,10)
  120. # Case 2: Bidirectional IPv6 connectivity
  121. @pytest.mark.esp32s3
  122. @pytest.mark.esp32h4
  123. @pytest.mark.openthread_br
  124. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  125. @pytest.mark.parametrize(
  126. 'port, config, count, app_path, beta_target, target', [
  127. ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
  128. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  129. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  130. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  131. 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h4|esp32h4|esp32s3'),
  132. ],
  133. indirect=True,
  134. )
  135. def test_Bidirectional_IPv6_connectivity(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  136. br = dut[2]
  137. cli = dut[1]
  138. assert Init_interface
  139. dut[0].serial.stop_redirect_thread()
  140. formBasicWiFiThreadNetwork(br, cli)
  141. try:
  142. assert ocf.is_joined_wifi_network(br)
  143. cli_global_unicast_addr = ocf.get_global_unicast_addr(cli, br)
  144. print('cli_global_unicast_addr', cli_global_unicast_addr)
  145. command = 'ping ' + str(cli_global_unicast_addr) + ' -c 10'
  146. out_str = subprocess.getoutput(command)
  147. print('ping result:\n', str(out_str))
  148. role = re.findall(r' (\d+)%', str(out_str))[0]
  149. assert role != '100'
  150. interface_name = ocf.get_host_interface_name()
  151. command = 'ifconfig ' + interface_name
  152. out_bytes = subprocess.check_output(command, shell=True, timeout=5)
  153. out_str = out_bytes.decode('utf-8')
  154. host_global_unicast_addr = re.findall(r'inet6 ((?:\w+:){7}\w+) prefixlen 64 scopeid 0x0<global>', str(out_str))
  155. rx_nums = 0
  156. for ip_addr in host_global_unicast_addr:
  157. txrx_nums = ocf.ot_ping(cli, str(ip_addr), 5)
  158. rx_nums = rx_nums + int(txrx_nums[1])
  159. assert rx_nums != 0
  160. finally:
  161. br.write('factoryreset')
  162. cli.write('factoryreset')
  163. time.sleep(3)
  164. # Case 3: Multicast forwarding from Wi-Fi to Thread network
  165. @pytest.mark.esp32s3
  166. @pytest.mark.esp32h4
  167. @pytest.mark.openthread_br
  168. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  169. @pytest.mark.parametrize(
  170. 'port, config, count, app_path, beta_target, target', [
  171. ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
  172. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  173. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  174. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  175. 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h4|esp32h4|esp32s3'),
  176. ],
  177. indirect=True,
  178. )
  179. def test_multicast_forwarding_A(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  180. br = dut[2]
  181. cli = dut[1]
  182. assert Init_interface
  183. dut[0].serial.stop_redirect_thread()
  184. formBasicWiFiThreadNetwork(br, cli)
  185. try:
  186. assert ocf.is_joined_wifi_network(br)
  187. br.write('bbr')
  188. br.expect('server16', timeout=5)
  189. assert ocf.thread_is_joined_group(cli)
  190. interface_name = ocf.get_host_interface_name()
  191. command = 'ping -I ' + str(interface_name) + ' -t 64 ff04::125 -c 10'
  192. out_str = subprocess.getoutput(command)
  193. print('ping result:\n', str(out_str))
  194. role = re.findall(r' (\d+)%', str(out_str))[0]
  195. assert role != '100'
  196. finally:
  197. br.write('factoryreset')
  198. cli.write('factoryreset')
  199. time.sleep(3)
  200. # Case 4: Multicast forwarding from Thread to Wi-Fi network
  201. @pytest.mark.esp32s3
  202. @pytest.mark.esp32h4
  203. @pytest.mark.openthread_br
  204. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  205. @pytest.mark.parametrize(
  206. 'port, config, count, app_path, beta_target, target', [
  207. ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
  208. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  209. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  210. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  211. 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h4|esp32h4|esp32s3'),
  212. ],
  213. indirect=True,
  214. )
  215. def test_multicast_forwarding_B(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  216. br = dut[2]
  217. cli = dut[1]
  218. assert Init_interface
  219. dut[0].serial.stop_redirect_thread()
  220. formBasicWiFiThreadNetwork(br, cli)
  221. try:
  222. assert ocf.is_joined_wifi_network(br)
  223. br.write('bbr')
  224. br.expect('server16', timeout=5)
  225. cli.write('udp open')
  226. cli.expect('Done', timeout=5)
  227. ocf.wait(cli, 3)
  228. myudp = ocf.udp_parameter('INET6', '::', 5090, 'ff04::125', False, 15.0, b'')
  229. udp_mission = threading.Thread(target=ocf.create_host_udp_server, args=(myudp, ))
  230. udp_mission.start()
  231. start_time = time.time()
  232. while not myudp.init_flag:
  233. if (time.time() - start_time) > 10:
  234. assert False
  235. assert ocf.host_joined_group('ff04::125')
  236. for num in range(0, 3):
  237. command = 'udp send ff04::125 5090 hello' + str(num)
  238. cli.write(command)
  239. cli.expect('Done', timeout=5)
  240. ocf.wait(cli, 0.5)
  241. while udp_mission.is_alive():
  242. time.sleep(1)
  243. finally:
  244. br.write('factoryreset')
  245. cli.write('factoryreset')
  246. time.sleep(3)
  247. assert b'hello' in myudp.udp_bytes
  248. # Case 5: discover dervice published by Thread device
  249. @pytest.mark.esp32s3
  250. @pytest.mark.esp32h4
  251. @pytest.mark.openthread_br
  252. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  253. @pytest.mark.parametrize(
  254. 'port, config, count, app_path, beta_target, target', [
  255. ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
  256. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  257. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  258. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  259. 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h4|esp32h4|esp32s3'),
  260. ],
  261. indirect=True,
  262. )
  263. def test_service_discovery_of_Thread_device(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  264. br = dut[2]
  265. cli = dut[1]
  266. assert Init_interface
  267. assert Init_avahi
  268. dut[0].serial.stop_redirect_thread()
  269. formBasicWiFiThreadNetwork(br, cli)
  270. try:
  271. assert ocf.is_joined_wifi_network(br)
  272. command = 'avahi-browse -rt _testyyy._udp'
  273. out_str = subprocess.getoutput(command)
  274. print('avahi-browse:\n', str(out_str))
  275. assert 'myTest' not in str(out_str)
  276. hostname = 'myTest'
  277. command = 'srp client host name ' + hostname
  278. cli.write(command)
  279. cli.expect('Done', timeout=5)
  280. cli_global_unicast_addr = ocf.get_global_unicast_addr(cli, br)
  281. print('cli_global_unicast_addr', cli_global_unicast_addr)
  282. command = 'srp client host address ' + str(cli_global_unicast_addr)
  283. cli.write(command)
  284. cli.expect('Done', timeout=5)
  285. port = '12348'
  286. command = 'srp client service add my-service _testyyy._udp ' + port
  287. cli.write(command)
  288. cli.expect('Done', timeout=5)
  289. cli.write('srp client autostart enable')
  290. cli.expect('Done', timeout=5)
  291. ocf.wait(cli, 3)
  292. command = 'avahi-browse -rt _testyyy._udp'
  293. out_str = subprocess.getoutput(command)
  294. print('avahi-browse:\n', str(out_str))
  295. assert 'myTest' in str(out_str)
  296. finally:
  297. br.write('factoryreset')
  298. cli.write('factoryreset')
  299. time.sleep(3)
  300. # Case 6: discover dervice published by Wi-Fi device
  301. @pytest.mark.esp32s3
  302. @pytest.mark.esp32h4
  303. @pytest.mark.openthread_br
  304. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  305. @pytest.mark.parametrize(
  306. 'port, config, count, app_path, beta_target, target', [
  307. ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
  308. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  309. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  310. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  311. 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h4|esp32h4|esp32s3'),
  312. ],
  313. indirect=True,
  314. )
  315. def test_service_discovery_of_WiFi_device(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  316. br = dut[2]
  317. cli = dut[1]
  318. assert Init_interface
  319. assert Init_avahi
  320. dut[0].serial.stop_redirect_thread()
  321. formBasicWiFiThreadNetwork(br, cli)
  322. try:
  323. assert ocf.is_joined_wifi_network(br)
  324. br_global_unicast_addr = ocf.get_global_unicast_addr(br, br)
  325. command = 'dns config ' + br_global_unicast_addr
  326. ocf.clean_buffer(cli)
  327. cli.write(command)
  328. cli.expect('Done', timeout=5)
  329. ocf.wait(cli, 1)
  330. command = 'dns resolve FA000123.default.service.arpa.'
  331. ocf.clean_buffer(cli)
  332. cli.write(command)
  333. cli.expect('Error', timeout=15)
  334. domain_name = ocf.get_domain()
  335. print('domain name is: ', domain_name)
  336. command = 'dns resolve ' + domain_name + '.default.service.arpa.'
  337. ocf.clean_buffer(cli)
  338. cli.write(command)
  339. cli.expect('TTL', timeout=10)
  340. cli.expect('Done', timeout=10)
  341. ocf.clean_buffer(cli)
  342. cli.write('dns browse _testxxx._udp.default.service.arpa')
  343. tmp = cli.expect(pexpect.TIMEOUT, timeout=5)
  344. assert 'Port:12347' not in str(tmp)
  345. ocf.host_publish_service()
  346. ocf.wait(cli, 5)
  347. ocf.clean_buffer(cli)
  348. cli.write('dns browse _testxxx._udp.default.service.arpa')
  349. tmp = cli.expect(pexpect.TIMEOUT, timeout=5)
  350. assert 'response for _testxxx' in str(tmp)
  351. assert 'Port:12347' in str(tmp)
  352. ocf.clean_buffer(cli)
  353. cli.write('dns service testxxx _testxxx._udp.default.service.arpa.')
  354. tmp = cli.expect(pexpect.TIMEOUT, timeout=5)
  355. assert 'response for testxxx' in str(tmp)
  356. assert 'Port:12347' in str(tmp)
  357. finally:
  358. ocf.host_close_service()
  359. br.write('factoryreset')
  360. cli.write('factoryreset')
  361. time.sleep(3)
  362. # Case 7: ICMP communication via NAT64
  363. @pytest.mark.esp32s3
  364. @pytest.mark.esp32h4
  365. @pytest.mark.openthread_br
  366. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  367. @pytest.mark.parametrize(
  368. 'port, config, count, app_path, beta_target, target', [
  369. ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
  370. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  371. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  372. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  373. 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h4|esp32h4|esp32s3'),
  374. ],
  375. indirect=True,
  376. )
  377. def test_ICMP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  378. br = dut[2]
  379. cli = dut[1]
  380. assert Init_interface
  381. dut[0].serial.stop_redirect_thread()
  382. formBasicWiFiThreadNetwork(br, cli)
  383. try:
  384. assert ocf.is_joined_wifi_network(br)
  385. host_ipv4_address = ocf.get_host_ipv4_address()
  386. print('host_ipv4_address: ', host_ipv4_address)
  387. rx_nums = ocf.ot_ping(cli, str(host_ipv4_address), 5)[1]
  388. assert rx_nums != 0
  389. finally:
  390. br.write('factoryreset')
  391. cli.write('factoryreset')
  392. time.sleep(3)
  393. # Case 8: UDP communication via NAT64
  394. @pytest.mark.esp32s3
  395. @pytest.mark.esp32h4
  396. @pytest.mark.openthread_br
  397. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  398. @pytest.mark.parametrize(
  399. 'port, config, count, app_path, beta_target, target', [
  400. ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
  401. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  402. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  403. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  404. 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h4|esp32h4|esp32s3'),
  405. ],
  406. indirect=True,
  407. )
  408. def test_UDP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  409. br = dut[2]
  410. cli = dut[1]
  411. assert Init_interface
  412. dut[0].serial.stop_redirect_thread()
  413. formBasicWiFiThreadNetwork(br, cli)
  414. try:
  415. assert ocf.is_joined_wifi_network(br)
  416. br.write('bbr')
  417. br.expect('server16', timeout=5)
  418. cli.write('udp open')
  419. cli.expect('Done', timeout=5)
  420. ocf.wait(cli, 3)
  421. host_ipv4_address = ocf.get_host_ipv4_address()
  422. print('host_ipv4_address: ', host_ipv4_address)
  423. myudp = ocf.udp_parameter('INET4', host_ipv4_address, 5090, '', False, 15.0, b'')
  424. udp_mission = threading.Thread(target=ocf.create_host_udp_server, args=(myudp, ))
  425. udp_mission.start()
  426. start_time = time.time()
  427. while not myudp.init_flag:
  428. if (time.time() - start_time) > 10:
  429. assert False
  430. for num in range(0, 3):
  431. command = 'udp send ' + host_ipv4_address + ' 5090 hello' + str(num)
  432. cli.write(command)
  433. cli.expect('Done', timeout=5)
  434. ocf.wait(cli, 0.5)
  435. while udp_mission.is_alive():
  436. time.sleep(1)
  437. finally:
  438. br.write('factoryreset')
  439. cli.write('factoryreset')
  440. time.sleep(3)
  441. assert b'hello' in myudp.udp_bytes
  442. # Case 9: TCP communication via NAT64
  443. @pytest.mark.esp32s3
  444. @pytest.mark.esp32h4
  445. @pytest.mark.openthread_br
  446. @pytest.mark.flaky(reruns=1, reruns_delay=1)
  447. @pytest.mark.parametrize(
  448. 'port, config, count, app_path, beta_target, target', [
  449. ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
  450. f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
  451. f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
  452. f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
  453. 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h4|esp32h4|esp32s3'),
  454. ],
  455. indirect=True,
  456. )
  457. def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
  458. br = dut[2]
  459. cli = dut[1]
  460. assert Init_interface
  461. dut[0].serial.stop_redirect_thread()
  462. formBasicWiFiThreadNetwork(br, cli)
  463. try:
  464. assert ocf.is_joined_wifi_network(br)
  465. br.write('bbr')
  466. br.expect('server16', timeout=5)
  467. cli.write('tcpsockclient open')
  468. cli.expect('Done', timeout=5)
  469. ocf.wait(cli, 3)
  470. host_ipv4_address = ocf.get_host_ipv4_address()
  471. connect_address = ocf.get_ipv6_from_ipv4(host_ipv4_address, br)
  472. print('connect_address is: ', connect_address)
  473. mytcp = ocf.tcp_parameter('INET4', host_ipv4_address, 12345, False, False, 15.0, b'')
  474. tcp_mission = threading.Thread(target=ocf.create_host_tcp_server, args=(mytcp, ))
  475. tcp_mission.start()
  476. start_time = time.time()
  477. while not mytcp.listen_flag:
  478. if (time.time() - start_time) > 10:
  479. assert False
  480. command = 'tcpsockclient connect ' + connect_address + ' 12345'
  481. cli.write(command)
  482. cli.expect('Successfully connected', timeout=10)
  483. start_time = time.time()
  484. while not mytcp.recv_flag:
  485. if (time.time() - start_time) > 10:
  486. assert False
  487. command = 'tcpsockclient send hello'
  488. cli.write(command)
  489. cli.expect('Done', timeout=5)
  490. while tcp_mission.is_alive():
  491. time.sleep(1)
  492. finally:
  493. br.write('factoryreset')
  494. cli.write('factoryreset')
  495. time.sleep(3)
  496. assert b'hello' in mytcp.tcp_bytes