Skip to content

Commit b111c84

Browse files
committed
Merge branch 'feat/upt_tests_new_runners' into 'master'
feat(ci): updated Ethernet test to align with new runners Closes IDF-14823 See merge request espressif/esp-idf!43573
2 parents f888ded + 4e6b35c commit b111c84

File tree

5 files changed

+116
-64
lines changed

5 files changed

+116
-64
lines changed

components/esp_eth/test_apps/main/esp_eth_test_l2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ TEST_CASE("heap utilization", "[ethernet_l2]")
637637
}
638638

639639
#define FORMAT_MAC(mac_addr, a, b, c, d, e, f) do { mac_addr[0] = a; mac_addr[1] = b; mac_addr[2] = c; mac_addr[3] = d; mac_addr[4] = e; mac_addr[5] = f; } while(0)
640-
TEST_CASE("w5500_multicast_filter", "[ethernet_l2]")
640+
TEST_CASE("multicast_filter", "[ethernet_l2]")
641641
{
642642
esp_eth_mac_t *mac = mac_init(NULL, NULL);
643643
TEST_ASSERT_NOT_NULL(mac);

components/esp_eth/test_apps/pytest_esp_eth.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,18 @@ def find_target_if(self, my_if: str = '') -> None:
3131
netifs.sort(reverse=True)
3232
logging.info('detected interfaces: %s', str(netifs))
3333

34-
for netif in netifs:
35-
# if no interface defined, try to find it automatically
36-
if my_if == '':
37-
if netif.find('eth') == 0 or netif.find('enp') == 0 or netif.find('eno') == 0:
38-
self.target_if = netif
39-
break
34+
if my_if == '':
35+
if 'dut_p1' in netifs:
36+
self.target_if = 'dut_p1'
4037
else:
41-
if netif.find(my_if) == 0:
42-
self.target_if = my_if
43-
break
38+
for netif in netifs:
39+
# if no interface defined, try to find it automatically
40+
if netif.find('eth') == 0 or netif.find('enp') == 0 or netif.find('eno') == 0:
41+
self.target_if = netif
42+
break
43+
elif my_if in netifs:
44+
self.target_if = my_if
45+
4446
if self.target_if == '':
4547
raise RuntimeError('network interface not found')
4648
logging.info('Use %s for testing', self.target_if)
@@ -132,8 +134,8 @@ def ethernet_int_emac_test(dut: IdfDut) -> None:
132134
dut.run_all_single_board_cases(group='esp_emac', timeout=240)
133135

134136

135-
def ethernet_l2_test(dut: IdfDut) -> None:
136-
target_if = EthTestIntf(ETH_TYPE)
137+
def ethernet_l2_test(dut: IdfDut, test_if: str = '') -> None:
138+
target_if = EthTestIntf(ETH_TYPE, test_if)
137139

138140
dut.expect_exact('Press ENTER to see the list of tests')
139141
dut.write('\n')

examples/network/bridge/pytest_example_bridge.py

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import socket
1010
import subprocess
1111
import time
12+
from collections.abc import Generator
1213
from concurrent.futures import Future
1314
from concurrent.futures import ThreadPoolExecutor
15+
from re import Match
1416

1517
import netifaces
1618
import paramiko # type: ignore
@@ -273,28 +275,38 @@ def send_brcast_msg_endnode_to_host(endnode: EndnodeSsh, host_brcast_ip: str, te
273275
return nc_host_out
274276

275277

276-
@pytest.mark.eth_w5500
277-
@pytest.mark.parametrize(
278-
'config',
279-
[
280-
'w5500',
281-
],
282-
indirect=True,
283-
)
284-
@idf_parametrize('target', ['esp32'], indirect=['target'])
285-
def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None:
286-
# ------------------------------ #
287-
# Pre-test testbed configuration #
288-
# ------------------------------ #
289-
# Get switch configuration info from the hostname
278+
def get_legacy_host_name_match() -> Match[str] | None:
290279
host_name = socket.gethostname()
291280
regex = r'ethVM-(\d+)-(\d+)'
292-
sw_info = re.search(regex, host_name, re.DOTALL)
293-
if sw_info is None:
294-
raise RuntimeError('Unexpected hostname')
281+
host_name_match = re.search(regex, host_name, re.DOTALL)
282+
return host_name_match
295283

296-
sw_num = int(sw_info.group(1))
297-
port_num = int(sw_info.group(2))
284+
285+
def get_host_info() -> tuple[int, int]:
286+
# Get switch configuration info from the hostname (legacy runners)
287+
sw_info = get_legacy_host_name_match()
288+
if sw_info is not None:
289+
sw_num = int(sw_info.group(1))
290+
port_num = int(sw_info.group(2))
291+
return sw_num, port_num
292+
else:
293+
# Get switch configuration info from the IP address of the `switch` interface (new runners)
294+
switch_if_ip = get_host_ip_by_interface('switch', netifaces.AF_INET)
295+
# Parse IP address: x.y.<sw_num>.<port_num>
296+
ip_parts = switch_if_ip.split('.')
297+
if len(ip_parts) == 4:
298+
sw_num = int(ip_parts[2])
299+
port_num = int(ip_parts[3])
300+
return sw_num, port_num
301+
else:
302+
raise RuntimeError('Unexpected switch IP address')
303+
304+
305+
def eth_bridge_test(dut: Dut, dev_user: str, dev_password: str) -> None:
306+
# ------------------------------ #
307+
# Pre-test testbed configuration #
308+
# ------------------------------ #
309+
sw_num, port_num = get_host_info()
298310
port_num_endnode = int(port_num) + 1 # endnode address is always + 1 to the host
299311

300312
endnode = EndnodeSsh(f'10.10.{sw_num}.{port_num_endnode}', ETHVM_ENDNODE_USER)
@@ -330,7 +342,10 @@ def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None:
330342
host_ip = get_host_ip_by_interface(host_if, netifaces.AF_INET)
331343
logging.info('Host IP %s', host_ip)
332344

333-
endnode_if = host_if # endnode is a clone of the host
345+
if get_legacy_host_name_match() is not None:
346+
endnode_if = host_if # endnode is a clone of the host (legacy runners)
347+
else:
348+
endnode_if = 'dut_p2' # interface name connected to the second port of the DUT (new runners)
334349
# Endnode MAC
335350
endnode_mac = get_endnode_mac_by_interface(endnode, endnode_if)
336351
logging.info('Endnode MAC %s', endnode_mac)
@@ -352,12 +367,12 @@ def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None:
352367
# TEST Objective 1: Ping the devices on the network
353368
# --------------------------------------------------
354369
# ping bridge
355-
ping_test = subprocess.call(f'ping {br_ip} -c 2', shell=True)
370+
ping_test = subprocess.call(['ping', br_ip, '-c', '2'])
356371
if ping_test != 0:
357372
raise RuntimeError('ESP bridge is not reachable')
358373

359374
# ping the end nodes of the network
360-
ping_test = subprocess.call(f'ping {endnode_ip} -c 2', shell=True)
375+
ping_test = subprocess.call(['ping', endnode_ip, '-c', '2'])
361376
if ping_test != 0:
362377
raise RuntimeError('End node is not reachable')
363378

@@ -526,13 +541,13 @@ def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None:
526541
logging.info('Drop `Endnode` MAC')
527542
dut.write('add --addr=' + endnode_mac + ' -d')
528543
dut.expect_exact('Bridge Config OK!')
529-
ping_test = subprocess.call(f'ping {endnode_ip} -c 2', shell=True)
544+
ping_test = subprocess.call(['ping', endnode_ip, '-c', '2'])
530545
if ping_test == 0:
531546
raise RuntimeError('End node should not be reachable')
532547
logging.info('Remove Drop `Endnode` MAC entry')
533548
dut.write('remove --addr=' + endnode_mac)
534549
dut.expect_exact('Bridge Config OK!')
535-
ping_test = subprocess.call(f'ping {endnode_ip} -c 2', shell=True)
550+
ping_test = subprocess.call(['ping', endnode_ip, '-c', '2'])
536551
if ping_test != 0:
537552
raise RuntimeError('End node is not reachable')
538553

@@ -565,9 +580,9 @@ def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None:
565580

566581
# Remove ARP record from Test host computer. ARP is broadcasted, hence Bridge port does not reply to a request since
567582
# it does not receive it (no forward to Bridge port). As a result, Bridge is not pingable.
568-
subprocess.call(f'sudo arp -d {br_ip}', shell=True)
569-
subprocess.call('arp -a', shell=True)
570-
ping_test = subprocess.call(f'ping {br_ip} -c 2', shell=True)
583+
subprocess.call(['sudo', 'arp', '-d', br_ip])
584+
subprocess.call(['arp', '-a'])
585+
ping_test = subprocess.call(['ping', br_ip, '-c', '2'])
571586
if ping_test == 0:
572587
raise RuntimeError('Bridge should not be reachable')
573588

@@ -577,7 +592,7 @@ def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None:
577592
dut.expect_exact('Bridge Config OK!')
578593
dut.write('add --addr=ff:ff:ff:ff:ff:ff -p 1 -c')
579594
dut.expect_exact('Bridge Config OK!')
580-
ping_test = subprocess.call(f'ping {br_ip} -c 2', shell=True)
595+
ping_test = subprocess.call(['ping', br_ip, '-c', '2'])
581596
if ping_test != 0:
582597
raise RuntimeError('Bridge is not reachable')
583598

@@ -588,3 +603,28 @@ def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None:
588603

589604
endnode.close()
590605
switch1.close()
606+
607+
608+
@pytest.fixture(scope='session', autouse=True)
609+
def setup_test_environment() -> Generator[None, None, None]:
610+
# Fixture code to run before any tests in the session
611+
# make sure dut_p2 is down (only for new runners)
612+
if get_legacy_host_name_match() is None:
613+
subprocess.call(['sudo', 'ip', 'link', 'set', 'down', 'dev', 'dut_p2'])
614+
615+
yield # Tests run here
616+
617+
# Optional teardown after all tests...
618+
619+
620+
@pytest.mark.eth_w5500
621+
@pytest.mark.parametrize(
622+
'config',
623+
[
624+
'w5500',
625+
],
626+
indirect=True,
627+
)
628+
@idf_parametrize('target', ['esp32'], indirect=['target'])
629+
def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None:
630+
eth_bridge_test(dut, dev_user, dev_password)

examples/protocols/l2tap/pytest_example_l2tap_echo.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,26 @@
2020

2121
@contextlib.contextmanager
2222
def configure_eth_if(eth_type: int, target_if: str = '') -> Iterator[socket.socket]:
23+
# try to determine which interface to use
24+
netifs = os.listdir('/sys/class/net/')
25+
# order matters - ETH NIC with the highest number is connected to DUT on CI runner
26+
netifs.sort(reverse=True)
27+
logging.info('detected interfaces: %s', str(netifs))
28+
29+
if target_if == '':
30+
if 'dut_p1' in netifs:
31+
target_if = 'dut_p1'
32+
else:
33+
for netif in netifs:
34+
# if no interface defined, try to find it automatically
35+
if netif.find('eth') == 0 or netif.find('enp') == 0 or netif.find('eno') == 0:
36+
target_if = netif
37+
break
38+
elif target_if not in netifs:
39+
target_if = ''
40+
2341
if target_if == '':
24-
# try to determine which interface to use
25-
netifs = os.listdir('/sys/class/net/')
26-
# order matters - ETH NIC with the highest number is connected to DUT on CI runner
27-
netifs.sort(reverse=True)
28-
logging.info('detected interfaces: %s', str(netifs))
29-
for netif in netifs:
30-
if netif.find('eth') == 0 or netif.find('enx') == 0 or netif.find('enp') == 0 or netif.find('eno') == 0:
31-
target_if = netif
32-
break
33-
if target_if == '':
34-
raise Exception('no network interface found')
42+
raise RuntimeError('network interface not found')
3543
logging.info('Use %s for testing', target_if)
3644

3745
so = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(eth_type))
@@ -76,7 +84,7 @@ def recv_eth_frame(eth_type: int, eth_if: str = '') -> str:
7684
return str(eth_frame.load.decode().rstrip('\x00'))
7785

7886

79-
def actual_test(dut: Dut) -> None:
87+
def actual_test(dut: Dut, test_if: str = '') -> None:
8088
# Get DUT's MAC address
8189
res = dut.expect(
8290
r'([\s\S]*)'
@@ -85,17 +93,17 @@ def actual_test(dut: Dut) -> None:
8593
dut_mac = res.group(2)
8694

8795
# Receive "ESP32 Hello frame"
88-
recv_eth_frame(ETH_TYPE_3)
96+
recv_eth_frame(ETH_TYPE_3, test_if)
8997

9098
# Sent a message and receive its echo
9199
message = 'ESP32 test message with EthType ' + hex(ETH_TYPE_1)
92-
echoed = send_recv_eth_frame(message, ETH_TYPE_1, dut_mac)
100+
echoed = send_recv_eth_frame(message, ETH_TYPE_1, dut_mac, test_if)
93101
if echoed == message:
94102
logging.info('PASS')
95103
else:
96104
raise Exception('Echoed message does not match!')
97105
message = 'ESP32 test message with EthType ' + hex(ETH_TYPE_2)
98-
echoed = send_recv_eth_frame(message, ETH_TYPE_2, dut_mac)
106+
echoed = send_recv_eth_frame(message, ETH_TYPE_2, dut_mac, test_if)
99107
if echoed == message:
100108
logging.info('PASS')
101109
else:

examples/protocols/sockets/udp_multicast/pytest_udp_multicast.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@ def find_target_if(my_if: str = '') -> str:
3636
netifs.sort(reverse=True)
3737
logging.info('detected interfaces: %s', str(netifs))
3838

39-
for netif in netifs:
40-
# if no interface defined, try to find it automatically
41-
if my_if == '':
42-
if netif.find('eth') == 0 or netif.find('enp') == 0 or netif.find('eno') == 0:
43-
return netif
39+
if my_if == '':
40+
if 'dut_p1' in netifs:
41+
return 'dut_p1'
4442
else:
45-
if netif.find(my_if) == 0:
46-
return my_if
43+
for netif in netifs:
44+
# if no interface defined, try to find it automatically
45+
if netif.find('eth') == 0 or netif.find('enp') == 0 or netif.find('eno') == 0:
46+
return netif
47+
elif my_if in netifs:
48+
return my_if
4749

4850
raise RuntimeError('network interface not found')
4951

@@ -135,15 +137,15 @@ def test_examples_udp_multicast_proto(dut: Dut, ip_version: str = 'ipv4', nic: s
135137
try:
136138
data, recv_addr = sock.recvfrom(1024)
137139
logging.info(f'Received {len(data)} bytes from {recv_addr}')
138-
except socket.timeout:
140+
except TimeoutError:
139141
raise RuntimeError(f'Timeout waiting for {ip_version} multicast message from ESP32')
140142

141143
# Check if received from expected source
142144
if recv_addr[0] != ip_addr or recv_addr[1] != PORT:
143145
raise RuntimeError(f'Received {ip_version} multicast message from unexpected source')
144146

145147
# Send multicast message
146-
message = '!!! Multicast test message from host !!!'.encode()
148+
message = b'!!! Multicast test message from host !!!'
147149
logging.info(f'Sending {ip_version} multicast message to {multicast_addr}:{PORT}')
148150
sock.sendto(message, (multicast_addr, PORT))
149151
if ip_version == 'ipv4_mapped':

0 commit comments

Comments
 (0)