From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 880615A0321 for ; Mon, 05 Aug 2024 14:37:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202312; t=1722861425; bh=91tl/Q84+fGe7qrWQCWJC5mpsni+ktI8cE/abuzbDTU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AspURz7kRFv7ietj0Ea5gVlUtMXcBshw7yyXk1493NQ0IUFJ63zKJp1jt9LQlGTIk Cu2ARQ/fQuyfc3xenVyC9rcEn22Hzl1yr/1YBtQE3Drfe9VMUMt8X/goNbAZB6ihs/ Of+s//nn7xAY78aHaoeAX9GB8NAlCaB38AxsXyp/iAxg23nDGw1tCImL6VKqOSMauH UwV844i77FwNjAbm9Aw8zqeTXbr1d2DcWLORKNC37qnJgIXm2KD7ltgZ5VWuUiwu/q dsqOAmxDV4HEeEt/7XEMTq3eCNl1OFkLIJyA3RiLkuwfJopjWkV55kHcIT6K9n4C/o zbZau40gjFkOA== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4WcwtT3HMCz4x8D; Mon, 5 Aug 2024 22:37:05 +1000 (AEST) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH v2 22/22] avocado: Convert basic pasta tests Date: Mon, 5 Aug 2024 22:37:01 +1000 Message-ID: <20240805123701.1720730-23-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240805123701.1720730-1-david@gibson.dropbear.id.au> References: <20240805123701.1720730-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: AVD5ZO2KGRZXQB6A2DSYNVXQV7R526ZW X-Message-ID-Hash: AVD5ZO2KGRZXQB6A2DSYNVXQV7R526ZW X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Cleber Rosa , David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Convert the old-style tests for pasta (DHCP, NDP, TCP and UDP transfers) to using avocado. There are a few differences in what we test, but this should generally improve coverage: * We run in a constructed network environment, so we no longer depend on the real host's networking configuration * We do independent setup for each individual test * We add explicit tests for --config-net, which we use to accelerate that setup for the TCP and UDP tests * The TCP and UDP tests now test transfers between the guest and a (simulated) remote site that's on a different network from the simulated pasta host. Thus testing the no NAT case that passt/pasta emphasizes. (We need to add tests for the NAT cases back in). Signed-off-by: David Gibson --- test/Makefile | 4 +- test/pasta/.gitignore | 1 + test/pasta/pasta.py | 138 +++++++++++++++++++++++++++++++++++++++++ test/tasst/__main__.py | 2 +- test/tasst/pasta.py | 52 ++++++++++++++++ 5 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 test/pasta/.gitignore create mode 100644 test/pasta/pasta.py create mode 100644 test/tasst/pasta.py diff --git a/test/Makefile b/test/Makefile index 6748d38a..ba249a5d 100644 --- a/test/Makefile +++ b/test/Makefile @@ -64,11 +64,11 @@ LOCAL_ASSETS = mbuto.img mbuto.mem.img podman/bin/podman QEMU_EFI.fd \ $(TESTDATA_ASSETS) ASSETS = $(DOWNLOAD_ASSETS) $(LOCAL_ASSETS) -AVOCADO_ASSETS = +AVOCADO_ASSETS = nstool small.bin medium.bin big.bin META_ASSETS = nstool small.bin medium.bin big.bin EXETER_SH = build/static_checkers.sh -EXETER_PY = build/build.py +EXETER_PY = build/build.py pasta/pasta.py EXETER_JOBS = $(EXETER_SH:%.sh=%.json) $(EXETER_PY:%.py=%.json) AVOCADO_JOBS = $(EXETER_JOBS) avocado/static_checkers.json diff --git a/test/pasta/.gitignore b/test/pasta/.gitignore new file mode 100644 index 00000000..a6c57f5f --- /dev/null +++ b/test/pasta/.gitignore @@ -0,0 +1 @@ +*.json diff --git a/test/pasta/pasta.py b/test/pasta/pasta.py new file mode 100644 index 00000000..491927a6 --- /dev/null +++ b/test/pasta/pasta.py @@ -0,0 +1,138 @@ +#! /usr/bin/env avocado-runner-avocado-classless + +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright Red Hat +# Author: David Gibson + +""" +avocado/pasta.py - Basic tests for pasta mode +""" + +import contextlib +import ipaddress + +import exeter + +from tasst import dhcp, dhcpv6, ndp, nstool +from tasst.pasta import Pasta +from tasst.scenario.simple import simple_net + +IN_FWD_PORT = 10002 +SPLICE_FWD_PORT = 10003 +FWD_OPTS = ['-t', f'{IN_FWD_PORT}', '-u', f'{IN_FWD_PORT}', + '-T', f'{SPLICE_FWD_PORT}', '-U', f'{SPLICE_FWD_PORT}'] + + +@contextlib.contextmanager +def pasta_unconfigured(*opts): + with simple_net() as simnet: + with nstool.unshare_snh('pastans', '-Ucnpf', '--mount-proc', + parent=simnet.simhost, capable=True) \ + as guestns: + with Pasta(host=simnet.simhost, opts=opts, ns=guestns) as pasta: + yield simnet, pasta.ns + + +@exeter.test +def test_ifname(): + with pasta_unconfigured() as (simnet, ns): + expected = set(['lo', simnet.IFNAME]) + exeter.assert_eq(set(ns.ifs()), expected) + + +@contextlib.contextmanager +def pasta_ndp_setup(): + with pasta_unconfigured() as (simnet, guestns): + guestns.ifup(simnet.IFNAME) + yield ndp.NdpTestScenario(client=guestns, + ifname=simnet.IFNAME, + network=simnet.IP6.network, + gateway=simnet.gw_ip6_ll.ip) + + +ndp.ndp_tests(pasta_ndp_setup) + + +@contextlib.contextmanager +def pasta_dhcp(): + with pasta_unconfigured() as (simnet, guestns): + yield dhcp.DhcpTestScenario(client=guestns, + ifname=simnet.IFNAME, + addr=simnet.IP4.ip, + gateway=simnet.GW_IP4.ip, + mtu=65520) + + +dhcp.dhcp_tests(pasta_dhcp) + + +@contextlib.contextmanager +def pasta_dhcpv6(): + with pasta_unconfigured() as (simnet, guestns): + yield dhcpv6.Dhcpv6TestScenario(client=guestns, + ifname=simnet.IFNAME, + addr=simnet.IP6.ip) + + +dhcpv6.dhcp6_tests(pasta_dhcpv6) + + +@contextlib.contextmanager +def pasta_configured(): + with pasta_unconfigured('--config-net', *FWD_OPTS) as (simnet, ns): + # Wait for DAD to complete on the --config-net address + ns.addr_wait(simnet.IFNAME, family='inet6', scope='global') + yield simnet, ns + + +@exeter.test +def test_config_net_addr(): + with pasta_configured() as (simnet, ns): + addrs = ns.addrs(simnet.IFNAME, scope='global') + exeter.assert_eq(set(addrs), set([simnet.IP4, simnet.IP6])) + + +@exeter.test +def test_config_net_route4(): + with pasta_configured() as (simnet, ns): + (defroute,) = ns.routes4(dst='default') + gateway = ipaddress.ip_address(defroute['gateway']) + exeter.assert_eq(gateway, simnet.GW_IP4.ip) + + +@exeter.test +def test_config_net_route6(): + with pasta_configured() as (simnet, ns): + (defroute,) = ns.routes6(dst='default') + gateway = ipaddress.ip_address(defroute['gateway']) + exeter.assert_eq(gateway, simnet.gw_ip6_ll.ip) + + +@exeter.test +def test_config_net_mtu(): + with pasta_configured() as (simnet, ns): + mtu = ns.mtu(simnet.IFNAME) + exeter.assert_eq(mtu, 65520) + + +@contextlib.contextmanager +def outward_transfer(): + with pasta_configured() as (simnet, ns): + yield ns, simnet.gw + + +@contextlib.contextmanager +def inward_transfer(): + with pasta_configured() as (simnet, ns): + yield simnet.gw, ns + + +@contextlib.contextmanager +def spliced_transfer(): + with pasta_configured() as (simnet, ns): + yield ns, simnet.simhost + + +if __name__ == '__main__': + exeter.main() diff --git a/test/tasst/__main__.py b/test/tasst/__main__.py index 491c68c9..058b3746 100644 --- a/test/tasst/__main__.py +++ b/test/tasst/__main__.py @@ -13,7 +13,7 @@ library of test helpers for passt & pasta import exeter # We import just to get the exeter tests, which flake8 can't see -from . import dhcp, dhcpv6, ndp, nstool, snh, transfer # noqa: F401 +from . import dhcp, dhcpv6, ndp, nstool, pasta, snh, transfer # noqa: F401 from .scenario import simple # noqa: F401 from .selftest import static_ifup, veth # noqa: F401 diff --git a/test/tasst/pasta.py b/test/tasst/pasta.py new file mode 100644 index 00000000..030affce --- /dev/null +++ b/test/tasst/pasta.py @@ -0,0 +1,52 @@ +#! /usr/bin/python3 + +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright Red Hat +# Author: David Gibson + +""" +Test A Simple Socket Transport + +pasta.py - Helpers for starting pasta +""" + +import contextlib +import os.path +import tempfile + + +PASTA_BIN = './pasta' + + +class Pasta(contextlib.AbstractContextManager): + """A managed pasta instance""" + + def __init__(self, *, host, ns, opts): + self.host = host + self.ns = ns + self.opts = opts + self.proc = None + + def __enter__(self): + self.tmpdir = tempfile.TemporaryDirectory() + piddir = self.tmpdir.__enter__() + pidfile = os.path.join(piddir, 'pasta.pid') + relpid = self.ns.relative_pid(self.host) + cmd = [f'{PASTA_BIN}', '-f', '-P', f'{pidfile}'] + list(self.opts) + \ + [f'{relpid}'] + self.proc = self.host.bg(*cmd) + self.proc.__enter__() + # Wait for the PID file to be written + pidstr = None + while not pidstr: + pidstr = self.host.output('cat', f'{pidfile}', check=False) + self.pid = int(pidstr) + return self + + def __exit__(self, *exc_details): + try: + self.host.fg('kill', '-TERM', f'{self.pid}') + self.proc.__exit__(*exc_details) + finally: + self.tmpdir.__exit__(*exc_details) -- 2.45.2