mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #14468 from miri64/riotctrl_shell.gnrc/enh/doctests
riotctrl_shell.gnrc: add doctests as parsing examples and bugfixes
This commit is contained in:
commit
0a86086967
107
dist/pythonlibs/riotctrl_shell/gnrc.py
vendored
107
dist/pythonlibs/riotctrl_shell/gnrc.py
vendored
@ -22,9 +22,18 @@ class GNRCICMPv6EchoParser(ShellInteractionParser):
|
||||
def _add_reply(res, reply):
|
||||
reply["seq"] = int(reply["seq"])
|
||||
reply["ttl"] = int(reply["ttl"])
|
||||
reply["rtt"] = float(reply["rtt"])
|
||||
if reply.get("rtt") is not None:
|
||||
reply["rtt"] = float(reply["rtt"])
|
||||
else:
|
||||
reply.pop("rtt", None)
|
||||
if reply.get("dup"):
|
||||
reply["dup"] = True
|
||||
else:
|
||||
reply.pop("dup", None)
|
||||
if reply.get("rssi") is not None:
|
||||
reply["rssi"] = int(reply["rssi"])
|
||||
else:
|
||||
reply.pop("rssi", None)
|
||||
if "replies" in res:
|
||||
res["replies"].append(reply)
|
||||
else:
|
||||
@ -35,6 +44,10 @@ class GNRCICMPv6EchoParser(ShellInteractionParser):
|
||||
stats["packet_loss"] = int(stats["packet_loss"])
|
||||
stats["rx"] = int(stats["rx"])
|
||||
stats["tx"] = int(stats["tx"])
|
||||
if stats.get("dup") is not None:
|
||||
stats["dup"] = int(stats["dup"])
|
||||
else:
|
||||
stats.pop("dup")
|
||||
res["stats"] = stats
|
||||
|
||||
@staticmethod
|
||||
@ -45,13 +58,62 @@ class GNRCICMPv6EchoParser(ShellInteractionParser):
|
||||
res["rtts"] = rtts
|
||||
|
||||
def parse(self, cmd_output):
|
||||
"""
|
||||
Parses output of GNRCIPv6NIB::nib_neigh_show()
|
||||
|
||||
>>> parser = GNRCICMPv6EchoParser()
|
||||
>>> res = parser.parse(
|
||||
... "12 bytes from fe80::385d:f965:106b:1114%6: "
|
||||
... "icmp_seq=0 ttl=64 rssi=-34 dBm time=8.839 ms\\n"
|
||||
... "12 bytes from fe80::385d:f965:106b:1114%6: "
|
||||
... "icmp_seq=1 ttl=64 rssi=-34 dBm time=6.925 ms\\n"
|
||||
... "12 bytes from fe80::385d:f965:106b:1114%6: "
|
||||
... "icmp_seq=2 ttl=64 rssi=-34 dBm time=7.885 ms\\n"
|
||||
... "--- fe80::385d:f965:106b:1114 PING statistics ---\\n"
|
||||
... "3 packets transmitted, 3 packets received, 0% packet loss\\n"
|
||||
... "round-trip min/avg/max = 6.925/7.883/8.839 ms\\n")
|
||||
>>> sorted(res)
|
||||
['replies', 'rtts', 'stats']
|
||||
>>> len(res["replies"])
|
||||
3
|
||||
>>> sorted(res["replies"][0])
|
||||
['rssi', 'rtt', 'seq', 'source', 'ttl']
|
||||
>>> res["replies"][0]["source"]
|
||||
'fe80::385d:f965:106b:1114%6'
|
||||
>>> res["replies"][0]["seq"]
|
||||
0
|
||||
>>> res["replies"][0]["ttl"]
|
||||
64
|
||||
>>> res["replies"][0]["rssi"]
|
||||
-34
|
||||
>>> res["replies"][0]["rtt"]
|
||||
8.839
|
||||
>>> sorted(res["stats"])
|
||||
['packet_loss', 'rx', 'tx']
|
||||
>>> res["stats"]["tx"]
|
||||
3
|
||||
>>> res["stats"]["rx"]
|
||||
3
|
||||
>>> res["stats"]["packet_loss"]
|
||||
0
|
||||
>>> sorted(res["rtts"])
|
||||
['avg', 'max', 'min']
|
||||
>>> res["rtts"]["min"]
|
||||
6.925
|
||||
>>> res["rtts"]["avg"]
|
||||
7.883
|
||||
>>> res["rtts"]["max"]
|
||||
8.839
|
||||
"""
|
||||
res = {}
|
||||
c_reply = re.compile(r"\d+ bytes from (?P<source>[0-9a-f:]+): "
|
||||
r"icmp_seq=(?P<seq>\d+) ttl=(?P<ttl>\d+) "
|
||||
r"(rssi=(?P<rssi>-?\d+) dBm )?"
|
||||
r"time=(?P<rtt>\d+.\d+) ms")
|
||||
c_reply = re.compile(r"\d+ bytes from (?P<source>[0-9a-f:]+(%\S+)?): "
|
||||
r"icmp_seq=(?P<seq>\d+) ttl=(?P<ttl>\d+)"
|
||||
r"( rssi=(?P<rssi>-?\d+) dBm)?"
|
||||
r"( time=(?P<rtt>\d+.\d+) ms)?"
|
||||
r"(?P<dup> \(DUP\))?")
|
||||
c_stats = re.compile(r"(?P<tx>\d+) packets transmitted, "
|
||||
r"(?P<rx>\d+) packets received, "
|
||||
r"((?P<dup>\d+) duplicates, )?"
|
||||
r"(?P<packet_loss>\d+)% packet loss")
|
||||
c_rtts = re.compile(r"round-trip min/avg/max = (?P<min>\d+.\d+)/"
|
||||
r"(?P<avg>\d+.\d+)/(?P<max>\d+.\d+) ms")
|
||||
@ -69,9 +131,7 @@ class GNRCICMPv6EchoParser(ShellInteractionParser):
|
||||
m = c_rtts.match(line)
|
||||
if m is not None:
|
||||
self._set_rtts(res, m.groupdict())
|
||||
return res
|
||||
# Unable to parse RTTs, so something went wrong.
|
||||
return None
|
||||
return res
|
||||
|
||||
|
||||
class GNRCPktbufStatsResults(dict):
|
||||
@ -129,6 +189,37 @@ class GNRCPktbufStatsParser(ShellInteractionParser):
|
||||
res["first_unused"]["size"] = int(first_unused["size"])
|
||||
|
||||
def parse(self, cmd_output):
|
||||
"""
|
||||
Parses output of GNRCPktbufStats::pktbuf_stats()
|
||||
|
||||
>>> parser = GNRCPktbufStatsParser()
|
||||
>>> res = parser.parse(
|
||||
... "packet buffer: first byte: 0x20001f54, last byte: 0x20003f54 "
|
||||
... "(size: 8192)\\n"
|
||||
... " position of last byte used: 312\\n"
|
||||
... "~ unused: 0x20001f54 (next: (nil), size: 8192) ~\\n")
|
||||
>>> sorted(res)
|
||||
['first_byte', 'first_unused', 'last_byte', 'last_byte_used', 'size']
|
||||
>>> res.is_empty()
|
||||
True
|
||||
>>> hex(res["first_byte"])
|
||||
'0x20001f54'
|
||||
>>> hex(res["last_byte"])
|
||||
'0x20003f54'
|
||||
>>> res["size"]
|
||||
8192
|
||||
>>> res["last_byte_used"]
|
||||
312
|
||||
>>> res.fullest_capacity() <= (res["last_byte_used"] / res["size"])
|
||||
True
|
||||
>>> sorted(res["first_unused"])
|
||||
['next', 'size', 'start']
|
||||
>>> hex(res["first_unused"]["start"])
|
||||
'0x20001f54'
|
||||
>>> res["first_unused"]["next"] # has no next according to dump
|
||||
>>> res["first_unused"]["size"]
|
||||
8192
|
||||
"""
|
||||
c_init1 = re.compile(r"packet buffer: "
|
||||
r"first byte: 0x(?P<first_byte>[0-9A-Fa-f]+), "
|
||||
r"last byte: 0x(?P<last_byte>[0-9A-Fa-f]+) "
|
||||
|
@ -19,7 +19,7 @@ def test_ping6():
|
||||
assert " -i 100 " in res
|
||||
|
||||
|
||||
def test_ping6_parser_success():
|
||||
def test_ping6_parser_success1():
|
||||
parser = riotctrl_shell.gnrc.GNRCICMPv6EchoParser()
|
||||
ping_res = parser.parse("""
|
||||
12 bytes from ::1: icmp_seq=0 ttl=64 time=0.435 ms
|
||||
@ -29,27 +29,46 @@ def test_ping6_parser_success():
|
||||
--- ::1 PING statistics ---
|
||||
3 packets transmitted, 3 packets received, 0% packet loss
|
||||
round-trip min/avg/max = 0.432/0.433/0.435 ms""")
|
||||
assert ping_res is not None
|
||||
assert ping_res
|
||||
assert "rtts" in ping_res
|
||||
assert "avg" in ping_res["rtts"]
|
||||
|
||||
|
||||
def test_ping6_parser_success2():
|
||||
parser = riotctrl_shell.gnrc.GNRCICMPv6EchoParser()
|
||||
ping_res = parser.parse("""
|
||||
12 bytes from ::1: icmp_seq=0 ttl=64
|
||||
12 bytes from ::1: icmp_seq=1 ttl=64
|
||||
12 bytes from ::1: icmp_seq=1 ttl=64 (DUP)
|
||||
|
||||
--- ::1 PING statistics ---
|
||||
2 packets transmitted, 3 packets received, 1 duplicates, 0% packet loss
|
||||
round-trip min/avg/max = 0.432/0.433/0.435 ms""")
|
||||
assert ping_res
|
||||
assert "rtts" in ping_res
|
||||
assert "avg" in ping_res["rtts"]
|
||||
assert len(ping_res["replies"]) == 3
|
||||
assert ping_res["replies"][2]["dup"]
|
||||
|
||||
|
||||
def test_ping6_parser_empty():
|
||||
parser = riotctrl_shell.gnrc.GNRCICMPv6EchoParser()
|
||||
ping_res = parser.parse("")
|
||||
assert ping_res is None
|
||||
assert not ping_res
|
||||
|
||||
|
||||
def test_ping6_parser_missing_rtts():
|
||||
parser = riotctrl_shell.gnrc.GNRCICMPv6EchoParser()
|
||||
ping_res = parser.parse("""
|
||||
12 bytes from ::1: icmp_seq=0 ttl=64 time=0.553 ms
|
||||
12 bytes from ::1: icmp_seq=1 ttl=64 time=0.496 ms
|
||||
12 bytes from ::1: icmp_seq=2 ttl=64 time=0.496 ms
|
||||
12 bytes from ::1: icmp_seq=0 ttl=64
|
||||
12 bytes from ::1: icmp_seq=1 ttl=64
|
||||
12 bytes from ::1: icmp_seq=2 ttl=64
|
||||
|
||||
--- ::1 PING statistics ---
|
||||
3 packets transmitted, 3 packets received, 0% packet loss""")
|
||||
assert ping_res is None
|
||||
assert ping_res
|
||||
assert "rtts" not in ping_res
|
||||
assert len(ping_res["replies"]) == 3
|
||||
|
||||
|
||||
def test_pktbuf():
|
||||
|
Loading…
Reference in New Issue
Block a user