def assert_dns_record(node: IPNode, dns_server_address: str, record: DNSRecord, port=53, timeout=60): require_cmd("dig", help_str="dig is required to run tests") server_cmd = "dig @{address} -p {port} -t {rtype} {domain_name}"\ .format(address=dns_server_address, rtype=record.rtype, domain_name=record.domain_name, port=port) out_regex = re.compile(r" *{name}[ \t]+{ttl}[ \t]+IN[ \t]+{rtype}[ \t]+" r"{rdata}" .format(rtype=record.rtype, ttl=record.ttl, name=record.domain_name, rdata=record.rdata)) t = 0 out = node.cmd(server_cmd.split(" ")) got_answer, match = search_dns_reply(out, out_regex) while t < timeout * 2 and match is None: t += 1 time.sleep(.5) out = node.cmd(server_cmd.split(" ")) got_answer, match = search_dns_reply(out, out_regex) assert got_answer, "No answer was received in %s" \ " from server %s in the reply of '%s':\n%s" \ % (node.name, dns_server_address, server_cmd, out) assert match is not None, "The expected data '%s' cannot be found " \ "in the DNS reply of '%s' received by %s from " \ "%s:\n%s" % (out_regex.pattern, server_cmd, node.name, dns_server_address, out)
def assert_bw(src: IPNode, dst: IPNode, bw_target: float, tolerance=1, v6=False): require_cmd("iperf3", help_str="iperf3 is required to run tests") iperf = dst.popen("iperf3 -s -J --one-off", universal_newlines=True) time.sleep(1) dst_ip = dst.intf().ip6 if v6 else dst.intf().ip src.popen("iperf3 -c {}".format(dst_ip), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) out, err = iperf.communicate() assert iperf.poll() == 0, "Cannot use iperf3 between {src} and {dst}: " \ "{err}".format(src=src, dst=dst, err=err) bws = [] data = json.loads(out) for sample in data["intervals"]: bw = int(sample["sum"]["bits_per_second"]) / 10**6 if bw_target - tolerance <= bw <= bw_target + tolerance: bws.append(bw) assert len(bws) >= 5, \ "Less than half of the pings between {src} and {dst}" \ " had the desired latency".format(src=src, dst=dst)
def check_tcp_connectivity(client: IPNode, server: IPNode, v6=False, server_port=80, server_itf=None, timeout=300) \ -> Tuple[int, bytes, bytes]: require_cmd("nc", help_str="nc is required to run tests") if server_itf is None: server_itf = server.defaultIntf() server_ip = server_itf.ip6 if v6 else server_itf.ip server_cmd = "nc %s -l %d" % ("-6" if v6 else "-4", server_port) server_p = server.popen(server_cmd.split(" ")) t = 0 client_cmd = "nc -z -w 1 -v %s %d" % (server_ip, server_port) client_p = client.popen(client_cmd.split(" ")) while t != timeout * 2 and client_p.wait() != 0: t += 1 if server_p.poll() is not None: out, err = server_p.communicate() assert False, \ "The netcat server used to check TCP connectivity failed" \ " with the output:\n[stdout]\n%s\n[stderr]\n%s" % (out, err) time.sleep(.5) client_p = client.popen(client_cmd.split(" ")) out, err = client_p.communicate() code = client_p.poll() server_p.send_signal(signal.SIGINT) server_p.wait() return code, out, err
def assert_delay(src: IPNode, dst: IPNode, delay_target: float, tolerance=1.5, v6=False): executable = "ping{v6}".format(v6="6" if v6 else "") require_cmd(executable, help_str="{executable} is required to run " "tests".format(executable=executable)) cmd = "{executable} -c 10 {dst}".format( executable=executable, dst=dst.intf().ip6 if v6 else dst.intf().ip) out, err, exitcode = src.pexec(cmd) assert exitcode == 0, "Cannot ping between {src} and {dst}: " \ "{err}".format(src=src, dst=dst, err=err) delays = [] for line in out.split("\n"): match = delay_regex.search(line) if match is not None: delay = float(match.group(1)) if delay_target - tolerance <= delay <= delay_target + tolerance: delays.append(delay) assert len(delays) >= 5, \ "Less than half of the pings between {src} and {dst}" \ " had the desired latency".format(src=src, dst=dst)
def assert_routing_table(router: IPNode, expected_prefixes: List[str], timeout=120): """ :param router: The router to test :param expected_prefixes: The list of prefixes to be in the routing table :param timeout: Time to wait for the routing convergence :return: """ cmd = "ip -%d route" % ip_network(str(expected_prefixes[0])).version out = router.cmd(cmd) prefixes = re.findall(r"|".join(expected_prefixes), out) count = 0 while any(item in prefixes for item in expected_prefixes): if count == timeout: pytest.fail("Cannot get all expected prefixes (%s) from routing " "table (%s)" % (expected_prefixes, prefixes)) time.sleep(1) count += 1 out = router.cmd(cmd) prefixes = re.findall(r"|".join(expected_prefixes), out) assert len(prefixes) == 0