From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202508 header.b=QTFCYLzK; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 5686D5A0272 for ; Thu, 02 Oct 2025 09:57:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202508; t=1759391830; bh=mD98ozcFjWU/fq1opmS+J0eN8L/mh8qboITS47zpFew=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QTFCYLzKWTmlHrYO9PsinxIlRw1cRy3piZgJTTNyAxiegTPwAhWGzsvH3EtGyqyZ+ cPQ3pkOQGQn41XHjwXs+lSyTxPoQq3V8txRqQw3uRHhzYSv64LVyghDLXQFgcaTv4M +OmDtoz+3AjDlpzS7nuewz+p+I63+eUSFqWuDYeOMvdrQLhI3AvcpOzQjc2W1Od/fg DCHT0phKKPCm/mqn19jq24baXDbo5nrRo1Rw0r0D9gGGn5cdtC6KBkDU0wezK7HYrT F80kuuYgIwZ1mXsw3Ae6a06zVamS44cN+ElVh4VuY4NxKnMgx0kH0BJnW4u51bPG35 etfzCNjanefog== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4cckfG3970z4wDd; Thu, 2 Oct 2025 17:57:10 +1000 (AEST) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH 3/3] test: Re-implement pasta NDP tests using tunbridge & exeter Date: Thu, 2 Oct 2025 17:57:08 +1000 Message-ID: <20251002075708.461931-4-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251002075708.461931-1-david@gibson.dropbear.id.au> References: <20251002075708.461931-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: RZJFS5C5JYOLMLT7AYJQAVI737WAQWSC X-Message-ID-Hash: RZJFS5C5JYOLMLT7AYJQAVI737WAQWSC 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: 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 pasta NDP tests from shell and our own DSL to Python using the exeter test protocol and tunbridge network simulation library. Signed-off-by: David Gibson --- test/Makefile | 2 +- test/pasta/dhcp | 5 ++++ test/pasta/ndp.py | 59 ++++++++++++++++++++++++++++++++++++++++++ test/run | 6 +++-- test/tasst/__init__.py | 4 +++ test/tasst/pasta.py | 40 ++++++++++++++++++++++++++++ 6 files changed, 113 insertions(+), 3 deletions(-) create mode 100755 test/pasta/ndp.py create mode 100644 test/tasst/pasta.py diff --git a/test/Makefile b/test/Makefile index f66c7e7e..95e3d75e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -67,7 +67,7 @@ ASSETS = $(DOWNLOAD_ASSETS) $(LOCAL_ASSETS) EXETER_SH = smoke/smoke.sh build/static_checkers.sh EXETER_PYPATH = exeter/py3:tunbridge/:. -EXETER_PYTHON = smoke/smoke.py build/build.py +EXETER_PYTHON = smoke/smoke.py build/build.py pasta/ndp.py EXETER_BATS = $(EXETER_SH:%=%.bats) $(EXETER_PYTHON:%=%.bats) BATS_FILES = $(EXETER_BATS) \ podman/test/system/505-networking-pasta.bats diff --git a/test/pasta/dhcp b/test/pasta/dhcp index e1c66be6..61279fbf 100644 --- a/test/pasta/dhcp +++ b/test/pasta/dhcp @@ -18,6 +18,11 @@ test Interface name nsout IFNAME ip -j link show | jq -rM '.[] | select(.link_type == "ether").ifname' check [ -n "__IFNAME__" ] +# Bring up the interface +ns ip link set dev __IFNAME__ up +# Wait for SLAAC & DAD to complete +ns while ! ip -j -6 addr show dev __IFNAME__ | jq -e '.[].addr_info.[] | select(.protocol == "kernel_ra")'; do sleep 0.1; done + test DHCP: address ns /sbin/dhclient -4 --no-pid __IFNAME__ nsout ADDR ip -j -4 addr show|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[0].local' diff --git a/test/pasta/ndp.py b/test/pasta/ndp.py new file mode 100755 index 00000000..8c7ce31e --- /dev/null +++ b/test/pasta/ndp.py @@ -0,0 +1,59 @@ +#! /usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# test/pasta/ndp.py - pasta NDP functionality +# +# Copyright Red Hat +# Author: David Gibson + +import contextlib +import dataclasses +from typing import Iterator + +import exeter +import tunbridge +import tasst + + +@dataclasses.dataclass +class UnconfiguredScenario(exeter.Scenario): + """Tests for a pasta instance without --config-net""" + + host: tunbridge.Site + guest: tunbridge.Site + ifname: str + addr6: tunbridge.ip.AddrMask6 + gw6: tunbridge.ip.Addr6 + + @exeter.scenariotest + def test_ifname(self) -> None: + ifs = tunbridge.ip.ifs(self.guest) + exeter.assert_eq(set(ifs), {'lo', self.ifname}) + + @tunbridge.ndp.NdpScenario.subscenario + def test_ndp(self) -> tunbridge.ndp.NdpScenario: + tunbridge.ip.ifup(self.guest, self.ifname) + return tunbridge.ndp.NdpScenario(client=self.guest, + ifname=self.ifname, + network=self.addr6.network, + gateway=self.gw6) + + +@UnconfiguredScenario.test +@contextlib.contextmanager +def simh_pasta_setup() -> Iterator[UnconfiguredScenario]: + with (tunbridge.sample.simple_host('host') as simh, + tunbridge.sample.isolated('guest', simh.site) as guest): + assert simh.ip6 is not None + assert simh.gw6_ll is not None + with tasst.pasta.pasta(simh.site, guest): + yield UnconfiguredScenario(host=simh.site, + guest=guest, + ifname=simh.ifname, + addr6=simh.ip6, + gw6=simh.gw6_ll) + + +if __name__ == '__main__': + exeter.main() diff --git a/test/run b/test/run index 3872a56e..4f09d767 100755 --- a/test/run +++ b/test/run @@ -43,8 +43,10 @@ KERNEL=${KERNEL:-"/boot/vmlinuz-$(uname -r)"} COMMIT="$(git log --oneline --no-decorate -1)" -# Let exeter tests written in Python find their modules +# Let exeter tests written in Python find their modules and binaries to run export PYTHONPATH=${BASEPATH}/exeter/py3:${BASEPATH}/tunbridge:${BASEPATH} +export PASTA=${PASTA:-${BASEPATH}/../pasta} + . lib/util . lib/context @@ -75,8 +77,8 @@ run() { exeter build/build.py exeter build/static_checkers.sh + exeter pasta/ndp.py setup pasta - test pasta/ndp test pasta/dhcp test pasta/tcp test pasta/udp diff --git a/test/tasst/__init__.py b/test/tasst/__init__.py index fd4fe9a8..f5386b3a 100644 --- a/test/tasst/__init__.py +++ b/test/tasst/__init__.py @@ -8,3 +8,7 @@ # # Copyright Red Hat # Author: David Gibson + +from . import pasta + +__all__ = ['pasta'] diff --git a/test/tasst/pasta.py b/test/tasst/pasta.py new file mode 100644 index 00000000..91f59036 --- /dev/null +++ b/test/tasst/pasta.py @@ -0,0 +1,40 @@ +#! /usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# TASST - Test A Simple Socket Transport +# +# test/tasst/pasta.py - Helpers for seeting up pasta instances +# +# Copyright Red Hat +# Author: David Gibson + +import contextlib +import os +from typing import Iterator + +import tunbridge + + +@contextlib.contextmanager +def pasta(host: tunbridge.Site, guest: tunbridge.Site, *opts: str) \ + -> Iterator[tunbridge.site.SiteProcess]: + if tunbridge.unshare.parent(guest) is not host: + raise ValueError("pasta guest must be a namespace under host site") + + # This implies guest is a namespace site + assert isinstance(guest, tunbridge.unshare.NsenterSite) + + exe = os.environ['PASTA'] + + with host.tempdir() as piddir: + pidfile = os.path.join(piddir, 'pasta.pid') + cmd = [exe, '-f', '-P', pidfile] + list(opts) + [f'{guest.pid}'] + with host.bg(*cmd, stop=True) as pasta: + # Wait for the PID file to be written + pidstr = None + while not pidstr: + pidstr = host.readfile(pidfile, check=False) + pid = int(pidstr) + print(f'pasta started, host: {host}, guest: {guest}, pid: {pid}') + yield pasta -- 2.51.0