diff --git a/psh/test-hw-ping-lan.py b/psh/test-hw-ping-lan.py new file mode 100644 index 00000000..a2dd12be --- /dev/null +++ b/psh/test-hw-ping-lan.py @@ -0,0 +1,194 @@ +# Phoenix-RTOS +# +# phoenix-rtos-tests +# +# ping command test +# +# Copyright 2023 Phoenix Systems +# Author: Damian Modzelewski +# +# This file is part of Phoenix-RTOS. +# +# %LICENSE% +# + +import psh.tools.psh as psh +import psh.tools.netset as netset + +GOOGLE_DNS = "8.8.8.8" +IP_LOOPBACK = "127.0.0.1" + + +def ping_output_regex(target, iteration): + iter_str = r"{" + str(iteration) + r"}" + + psh_output_regex = "PING [()0-9a-z.: ]+ data bytes" + psh.EOL + psh_output_regex += r"(([0-9]+[a-z\s]+ " + psh_output_regex += str(target) + psh_output_regex += r": ttl=[0-9]+ icmp_seq=[0-9]+ time=([0-9.]+) ms)" + psh_output_regex += f"{psh.EOL}){iter_str}" + + return psh_output_regex + + +def ping_error_regex(error_msg): + ping_error_regex = r"PING [()0-9a-z.: ]+ data bytes" + psh.EOL + error_msg + psh.EOL + + return ping_error_regex + + +def psh_ping_help(p): + help = ( + "Usage: ping [options] address", + "Options", + " -h: prints help", + " -c: count, number of requests to be sent, default 5", + " -i: interval in milliseconds, default 1000", + " -t: IP Time To Live, default 64", + " -s: payload size, default 56, maximum 2040", + " -W: socket timetout, default 2000", + "", + ) + psh.assert_cmd(p, "ping -h", expected=help, result="success", is_regex=False) + + +def psh_ping_errors(p): + # invalid ping target + ping_target = "" + psh.assert_cmd( + p, + f"ping -c 4 -W 200 {ping_target}", + expected="ping: Expected address!", + result="fail", + is_regex=False, + ) + + # invalid ping count + psh.assert_cmd( + p, + f"ping -c -W 200 {GOOGLE_DNS}", + expected="ping: Wrong count value!", + result="fail", + is_regex=False, + ) + + # invalid ttl value + psh.assert_cmd( + p, + f"ping -t -W 200 {GOOGLE_DNS}", + expected="ping: Wrong ttl value!", + result="fail", + is_regex=False, + ) + + # invalid interval value + psh.assert_cmd( + p, + f"ping -i -W 200 {GOOGLE_DNS}", + expected="ping: Wrong interval value!", + result="fail", + is_regex=False, + ) + + # invalid timeout + psh.assert_cmd( + p, + f"ping -W {GOOGLE_DNS}", + expected="ping: Wrong timeout value!", + result="fail", + is_regex=False, + ) + + # invlid_payload_len + psh.assert_cmd( + p, + f"ping -s 2041 -W 200 {GOOGLE_DNS}", + expected="ping: Wrong payload len", + result="fail", + is_regex=False, + ) + + +def psh_ping_en_disabled(p): + # for all possible case of use ping command i and W flag are used to speed up test process + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {GOOGLE_DNS}", + expected=ping_error_regex("ping: Fail to send a packet!"), + result="fail", + is_regex=True, + ) + + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {IP_LOOPBACK}", + expected=ping_output_regex(IP_LOOPBACK, 5), + result="success", + is_regex=True, + ) + + +def psh_direct_target_ping(p): + counter = 0 + # right now it uses only targets defined in ip_table which are same targets as before + an interface of tested evk + avaliable_targets = netset.ip_table() + for x in avaliable_targets: + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {x}", + expected=ping_output_regex(x, 5) + "|Host timeout" + psh.EOL, + result="dont-check", + is_regex=True, + ) + if psh.get_exit_code(p) == 0: + counter += 1 + assert counter >= 2 + + +def psh_ping(p): + # self ping + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {IP_LOOPBACK}", + expected=ping_output_regex(IP_LOOPBACK, 5), + result="success", + is_regex=True, + ) + + # find TTL route + for i in range(10, 50, 10): + counter = 0 + for x in range(0, 5): + psh.assert_cmd( + p, + f"ping -t {i} -i 10 -W 200 192.168.72.{i+x}", + expected=ping_output_regex(f"192.168.72.{i+x}", 5) + "|" + ping_error_regex("Host timeout"), + result="dont-check", + is_regex=True, + ) + + if psh.get_exit_code(p) == 0: + counter += 1 + assert counter >= 2 + + # using "localhost" as desired target to check address resolver + ping_target = "localhost" + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {ping_target}", + expected=ping_output_regex(IP_LOOPBACK, 5), + result="success", + is_regex=True, + ) + + +@psh.run +def harness(p): + psh_ping_help(p) + psh_ping_errors(p) + psh_ping_en_disabled(p) + + netset.en_setup(p, eth="en1") + + psh_direct_target_ping(p) + psh_ping(p) diff --git a/psh/test-hw-ping-wan.py b/psh/test-hw-ping-wan.py new file mode 100644 index 00000000..c9ddb675 --- /dev/null +++ b/psh/test-hw-ping-wan.py @@ -0,0 +1,189 @@ +# Phoenix-RTOS +# +# phoenix-rtos-tests +# +# ping command test +# +# Copyright 2023 Phoenix Systems +# Author: Damian Modzelewski +# +# This file is part of Phoenix-RTOS. +# +# %LICENSE% +# + +import psh.tools.psh as psh +import psh.tools.netset as netset + +GOOGLE_DNS = "8.8.8.8" +IP_LOOPBACK = "127.0.0.1" + + +def ping_output_regex(target, iteration): + iter_str = r"{" + str(iteration) + r"}" + + psh_output_regex = r"PING [()0-9a-z-.: ]+ data bytes" + psh.EOL + psh_output_regex += r"(([0-9]+[a-z\s]+ " + psh_output_regex += str(target) + psh_output_regex += r": ttl=[0-9]+ icmp_seq=[0-9]+ time=([0-9.]+) ms)" + psh_output_regex += f"{psh.EOL}){iter_str}" + + print(psh_output_regex) + return psh_output_regex + + +def ping_error_regex(error_msg): + ping_error_regex = r"PING [()0-9a-z.: ]+ data bytes" + psh.EOL + error_msg + psh.EOL + + return ping_error_regex + + +def psh_ping_en_disabled(p): + # for all possible case of use ping command i and W flag are used to speed up test process + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {GOOGLE_DNS}", + expected=ping_error_regex("ping: Fail to send a packet!"), + result="fail", + is_regex=True, + ) + + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {IP_LOOPBACK}", + expected=ping_output_regex(IP_LOOPBACK, 5), + result="success", + is_regex=True, + ) + + +def psh_ping_help(p): + help = ( + "Usage: ping [options] address", + "Options", + " -h: prints help", + " -c: count, number of requests to be sent, default 5", + " -i: interval in milliseconds, default 1000", + " -t: IP Time To Live, default 64", + " -s: payload size, default 56, maximum 2040", + " -W: socket timetout, default 2000", + "", + ) + psh.assert_cmd(p, "ping -h", expected=help, result="success", is_regex=False) + + +def psh_ping(p): + counter = 0 + + # self ping + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {IP_LOOPBACK}", + expected=ping_output_regex(IP_LOOPBACK, 5), + result="success", + is_regex=True, + ) + + # google dns ping after linuxrc run (success) + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {GOOGLE_DNS}", + expected=ping_output_regex(GOOGLE_DNS, 5) + "|Host timeout" + psh.EOL, + result="dont-check", + is_regex=True, + ) + + # find TTL route + for i in range(1, 10): + psh.assert_cmd( + p, + f"ping -t {i} -i 10 -W 200 {GOOGLE_DNS}", + expected=ping_output_regex(GOOGLE_DNS, 5) + "|Host timeout" + psh.EOL, + result="dont-check", + is_regex=True, + ) + + if psh.get_exit_code(p) == 0: + counter += 1 + + assert counter > 0 + + # long ping (ping tics are every second that's why timeout 50 + 5 secs for hiccups) + psh.assert_cmd( + p, + f"ping -c 50 -i 10 -W 200 {GOOGLE_DNS}", + expected=ping_output_regex(GOOGLE_DNS, 50), + result="success", + is_regex=True, + ) + + # ping with long time to respond (IBM cloud name server). + ping_target = "67.228.254.4" + psh.assert_cmd( + p, + f"ping -i 10 -W 200 {ping_target}", + expected=ping_output_regex(ping_target, 5), + result="success", + is_regex=True, + ) + + # ping max payload (truncated to 1480) + psh.assert_cmd( + p, + f"ping -s 2000 -i 10 -W 200 {ping_target}", + expected=ping_output_regex(ping_target, 5), + result="success", + is_regex=True, + ) + + # ping min payload + psh.assert_cmd( + p, f"ping -i 200 {ping_target}", expected=ping_output_regex(ping_target, 5), result="success", is_regex=True + ) + + # ping max payload (Cloudflare DNS capable to hold payload) + ping_target = "1.0.0.1" + psh.assert_cmd( + p, + f"ping -s 2000 -i 10 -W 200 {ping_target}", + expected=ping_output_regex(ping_target, 5), + result="success", + is_regex=True, + ) + + +def psh_ping_name_resolve(p): + ping_target = [ + "google.com", + "controld.com", + "quad9.net", + "opendns.com", + "alternate-dns.com", + "adguard-dns.io", + "publicdns.xyz", + "iana.org", + "ns1.haninternet.net", + ] + + for x in ping_target: + psh.assert_cmd( + p, + f"ping -W 3000 {str(x)}", + expected=ping_output_regex(r"[0-9.]+", 5), + result="success", + is_regex=True, + ) + + +@psh.run +def harness(p): + psh_ping_en_disabled(p) + + netset.en_setup(p, eth="en1", wan=True) + + psh_ping_help(p) + psh_ping(p) + + netset.en_setup(p, eth="en1", dynamic=True) + + psh_ping_name_resolve(p) diff --git a/psh/test.yaml b/psh/test.yaml index 8aeca9c5..9d47d7f9 100644 --- a/psh/test.yaml +++ b/psh/test.yaml @@ -13,7 +13,7 @@ test: - name: auth harness: test-auth.py - #FIXME - test-pshlogin.py is only for targets with root + # FIXME - test-pshlogin.py is only for targets with root - name: pshlogin harness: test-pshlogin.py targets: @@ -82,3 +82,17 @@ test: # https://github.com/phoenix-rtos/phoenix-rtos-project/issues/866 exclude: [armv7m7-imxrt117x-evk] harness: test-exit.py + + - name: ping_lan + harness: test-hw-ping-lan.py + targets: + # Ethernet driver is not available on all EVK except armv7a7-imx6ull-evk + # and Ethernet capabilities are different for EVK and emulators + exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo, armv7a9-zynq7000-zedboard, armv7a9-zynq7000-qemu, ia32-generic-qemu, riscv64-generic-qemu] + + - name: ping_wan + harness: test-hw-ping-wan.py + targets: + # Ethernet driver is not available on all EVK except armv7a7-imx6ull-evk + # and Ethernet capabilities are different for EVK and emulators + exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo, armv7a9-zynq7000-zedboard, armv7a9-zynq7000-qemu, ia32-generic-qemu, riscv64-generic-qemu] diff --git a/psh/tools/netset.py b/psh/tools/netset.py new file mode 100644 index 00000000..060345e3 --- /dev/null +++ b/psh/tools/netset.py @@ -0,0 +1,92 @@ +# Phoenix-RTOS +# +# phoenix-rtos-tests +# +# ping command test +# +# Copyright 2023 Phoenix Systems +# Author: Damian Modzelewski +# +# This file is part of Phoenix-RTOS. +# +# %LICENSE% +# + +from typing import Optional +import psh.tools.psh as psh +import subprocess +import re +import time + + +def ip_table(): + possible_ip = ( + "192.168.72.20", + "192.168.72.21", + "192.168.72.120", + "192.168.72.121", + ) + return possible_ip + + +def host_interface(): + out = subprocess.run("ifconfig", encoding="ascii", stdout=subprocess.PIPE, check=True) + eth_device = re.findall("eth[0-9]:.+\n.+[0-9]+", out.stdout) + inet = re.findall("inet [0-9.]+", str(eth_device)) + netmask = re.findall("netmask [0-9.]+", str(eth_device)) + host_setup = inet + netmask + return host_setup + + +def en_setup( + p, + eth="en1", + up: Optional[bool] = True, + wan: Optional[bool] = False, + ip: Optional[str] = None, + dynamic: Optional[bool] = False, +): + host_setup = host_interface() + host_ip = host_setup[0] + host_netmask = host_setup[1] + if ip is None: + print(host_ip) + ip_split = re.findall(r"([0-9]{1,3})", host_ip) + print(ip_split) + if int(ip_split[3]) >= 100: + ip_split[3] = "150" + else: + ip_split[3] = "1" + ip_split[3] + + desired_target_ip = ".".join(ip_split) + ip_split[3] = "1" + default_gw = ".".join(ip_split) + + else: + desired_target_ip = ip + ip_split = re.findall(r"([0-9]{1,3})", ip) + ip_split[3] = "1" + default_gw = ".".join(ip_split) + + ifconfig_setup_cmd = f"ifconfig {eth} {desired_target_ip} {host_netmask} " + + if wan: + route_setup_cmd = f"./sbin/route add default gw {default_gw} {eth}" + else: + route_setup_cmd = f"./sbin/route add -net {desired_target_ip} {eth}" + + if up: + ifconfig_setup_cmd += "up " + + if not dynamic: + psh.assert_prompt_after_cmd(p, ifconfig_setup_cmd, "success") + psh.assert_prompt_after_cmd(p, route_setup_cmd, "success") + else: + psh.assert_prompt_after_cmd(p, "ifconfig en1 dynamic", "success") + + time.sleep(1) + + +@psh.run +def harness(p): + en_setup(p)