public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: crosa@redhat.com, jarichte@redhat.com,
	David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 10/27] tasst: Helper functions for executing commands in different places
Date: Tue, 27 Jun 2023 12:54:11 +1000	[thread overview]
Message-ID: <20230627025429.2209702-11-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20230627025429.2209702-1-david@gibson.dropbear.id.au>

Add a library "tasst" for use in avocado tests of passt & pasta.  We start
by adding the outline of logic to run commands in various places (e.g.
namespaces, VMs).  We add some avocado tests for the test library itself,
tagged 'meta' to distinguish it from tests for passt/pasta proper.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 test/Makefile         |  8 +++-
 test/tasst/exesite.py | 99 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+), 2 deletions(-)
 create mode 100644 test/tasst/exesite.py

diff --git a/test/Makefile b/test/Makefile
index c06d63b6..0e641024 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -243,10 +243,14 @@ flake8: $(VENV)
 #
 # C0116 missing-function-docstring
 #    We have a bunch of trivial functions for which docstrings would be overkill
-# 
+# C0103 invalid-name
+#    As well as complaining about bad formatting style, this complains
+#    about short identifiers (< 3 characters?).  For many locals and
+#    some methods, this is stupid.
 pylint: $(VENV)
 	$(VENV)/bin/pylint \
-                --disable=C0116 \
+	        --disable=C0116 \
+	        --disable=C0103 \
 	    $(PYPKGS)
 
 .PHONY: check
diff --git a/test/tasst/exesite.py b/test/tasst/exesite.py
new file mode 100644
index 00000000..9f037f77
--- /dev/null
+++ b/test/tasst/exesite.py
@@ -0,0 +1,99 @@
+#! /usr/bin/env avocado-runner-avocado-classless
+
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright Red Hat
+# Author: David Gibson <david@gibson.dropbear.id.au>
+
+"""
+Test A Simple Socket Transport
+
+tasst/exesite.py - Manage simulated network sites for testing
+"""
+
+
+import contextlib
+
+import avocado
+from avocado.utils.process import CmdError
+from avocado_classless.test import assert_eq, assert_raises, test_output
+
+
+class Site(contextlib.AbstractContextManager):
+    """
+    A (usually virtual or simulated) location where we can execute
+    commands and configure networks.
+
+    """
+
+    def __init__(self, name):
+        self.name = name   # For debugging
+
+    def hostify(self, cmd, **kwargs):
+        raise NotImplementedError
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *exc_details):
+        pass
+
+    def output(self, cmd, strip_trail_nl=False, **kwargs):
+        kwargs['strip_trail_nl'] = strip_trail_nl
+        cmd, kwargs = self.hostify(cmd, **kwargs)
+        return avocado.utils.process.system_output(cmd, **kwargs)
+
+    def fg(self, cmd, **kwargs):
+        cmd, kwargs = self.hostify(cmd, **kwargs)
+        return avocado.utils.process.system(cmd, **kwargs)
+
+    def require_cmds(self, *cmds):
+        missing = [c for c in cmds
+                   if self.fg(f'type {c}', ignore_status=True) != 0]
+        if missing:
+            raise avocado.TestCancel(
+                f"Missing commands {', '.join(missing)} on {self.name}")
+
+
+def test_site(sitefn):
+    def test_true(s):
+        with s as site:
+            site.fg('true')
+
+    def test_false(s):
+        with s as site:
+            assert_raises(CmdError, site.fg, 'false')
+
+    def test_echo(s):
+        with s as site:
+            msg = 'Hello tasst'
+            out = site.output(f'echo {msg}')
+            assert_eq(out, msg.encode('utf-8') + b'\n')
+
+    def test_timeout(s):
+        with s as site:
+            site.fg('sleep infinity', timeout=0.1, ignore_status=True)
+
+    return test_output(test_true, test_false, test_echo, test_timeout)(sitefn)
+
+
+class RealHost(Site):
+    """Represents the host on which the tests are running (as opposed
+    to some simulated host created by the tests)
+
+    """
+
+    def __init__(self):
+        super().__init__('REAL_HOST')
+
+    def hostify(self, cmd, *, sudo=False, **kwargs):
+        assert not sudo, "BUG: Shouldn't run commands with privilege on host"
+        return cmd, kwargs
+
+
+REAL_HOST = RealHost()
+
+
+@test_site
+def real_host():
+    return REAL_HOST
-- 
@@ -0,0 +1,99 @@
+#! /usr/bin/env avocado-runner-avocado-classless
+
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright Red Hat
+# Author: David Gibson <david@gibson.dropbear.id.au>
+
+"""
+Test A Simple Socket Transport
+
+tasst/exesite.py - Manage simulated network sites for testing
+"""
+
+
+import contextlib
+
+import avocado
+from avocado.utils.process import CmdError
+from avocado_classless.test import assert_eq, assert_raises, test_output
+
+
+class Site(contextlib.AbstractContextManager):
+    """
+    A (usually virtual or simulated) location where we can execute
+    commands and configure networks.
+
+    """
+
+    def __init__(self, name):
+        self.name = name   # For debugging
+
+    def hostify(self, cmd, **kwargs):
+        raise NotImplementedError
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *exc_details):
+        pass
+
+    def output(self, cmd, strip_trail_nl=False, **kwargs):
+        kwargs['strip_trail_nl'] = strip_trail_nl
+        cmd, kwargs = self.hostify(cmd, **kwargs)
+        return avocado.utils.process.system_output(cmd, **kwargs)
+
+    def fg(self, cmd, **kwargs):
+        cmd, kwargs = self.hostify(cmd, **kwargs)
+        return avocado.utils.process.system(cmd, **kwargs)
+
+    def require_cmds(self, *cmds):
+        missing = [c for c in cmds
+                   if self.fg(f'type {c}', ignore_status=True) != 0]
+        if missing:
+            raise avocado.TestCancel(
+                f"Missing commands {', '.join(missing)} on {self.name}")
+
+
+def test_site(sitefn):
+    def test_true(s):
+        with s as site:
+            site.fg('true')
+
+    def test_false(s):
+        with s as site:
+            assert_raises(CmdError, site.fg, 'false')
+
+    def test_echo(s):
+        with s as site:
+            msg = 'Hello tasst'
+            out = site.output(f'echo {msg}')
+            assert_eq(out, msg.encode('utf-8') + b'\n')
+
+    def test_timeout(s):
+        with s as site:
+            site.fg('sleep infinity', timeout=0.1, ignore_status=True)
+
+    return test_output(test_true, test_false, test_echo, test_timeout)(sitefn)
+
+
+class RealHost(Site):
+    """Represents the host on which the tests are running (as opposed
+    to some simulated host created by the tests)
+
+    """
+
+    def __init__(self):
+        super().__init__('REAL_HOST')
+
+    def hostify(self, cmd, *, sudo=False, **kwargs):
+        assert not sudo, "BUG: Shouldn't run commands with privilege on host"
+        return cmd, kwargs
+
+
+REAL_HOST = RealHost()
+
+
+@test_site
+def real_host():
+    return REAL_HOST
-- 
2.41.0


  parent reply	other threads:[~2023-06-27  2:54 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-27  2:54 [PATCH 00/27] RFC: Start converting passt & pasta tests to Avocado using special plugin David Gibson
2023-06-27  2:54 ` [PATCH 01/27] avocado: Make a duplicate copy of testsuite for comparison purposes David Gibson
2023-06-27  2:54 ` [PATCH 02/27] avocado: Don't double download assets for test/ and oldtest/ David Gibson
2023-06-27  2:54 ` [PATCH 03/27] avocado: Move static checkers to avocado David Gibson
2023-06-27  2:54 ` [PATCH 04/27] avocado: Introduce "avocado-classless" plugin, runner and outline David Gibson
2023-06-27  2:54 ` [PATCH 05/27] avocado, test: Add static checkers for Python code David Gibson
2023-06-27  2:54 ` [PATCH 06/27] avocado: Resolver implementation for avocado-classless plugin David Gibson
2023-06-27  2:54 ` [PATCH 07/27] avocado: Add basic assertion helpers to " David Gibson
2023-06-27  2:54 ` [PATCH 08/27] tasst, avocado: Introduce library of common test helpers David Gibson
2023-06-27  2:54 ` [PATCH 09/27] avocado-classless: Test matrices by composition David Gibson
2023-06-27  2:54 ` David Gibson [this message]
2023-06-27  2:54 ` [PATCH 11/27] avocado-classless: Allow overriding default timeout David Gibson
2023-06-27  2:54 ` [PATCH 12/27] avocado: Convert build tests to avocado David Gibson
2023-06-27  2:54 ` [PATCH 13/27] tasst: Add helpers for running background commands on sites David Gibson
2023-06-27  2:54 ` [PATCH 14/27] tasst: Add helper to get network interface names for a site David Gibson
2023-06-27  2:54 ` [PATCH 15/27] tasst: Add helpers to run commands with nstool David Gibson
2023-06-27  2:54 ` [PATCH 16/27] tasst: Add ifup and network address helpers to Site David Gibson
2023-06-27  2:54 ` [PATCH 17/27] tasst: Helper for creating veth devices between namespaces David Gibson
2023-06-27  2:54 ` [PATCH 18/27] tasst: Add helper for getting MTU of a network interface David Gibson
2023-06-27  2:54 ` [PATCH 19/27] tasst: Add helper to wait for IP address to appear David Gibson
2023-06-27  2:54 ` [PATCH 20/27] tasst: Add helpers for getting a site's routes David Gibson
2023-06-27  2:54 ` [PATCH 21/27] tasst: Helpers to test transferring data between sites David Gibson
2023-06-27  2:54 ` [PATCH 22/27] tasst: IP address allocation helpers David Gibson
2023-06-27  2:54 ` [PATCH 23/27] tasst: Helpers for running daemons with a pidfile David Gibson
2023-06-27  2:54 ` [PATCH 24/27] tasst: Helpers for testing NDP behaviour David Gibson
2023-06-27  2:54 ` [PATCH 25/27] tasst: Helpers for testing DHCP & DHCPv6 behaviour David Gibson
2023-06-27  2:54 ` [PATCH 26/27] tasst: Helpers to construct a simple network environment for tests David Gibson
2023-06-27  2:54 ` [PATCH 27/27] avocado: Convert basic pasta tests David Gibson
2023-07-05  0:30   ` Stefano Brivio
2023-07-05  3:27     ` David Gibson
2023-07-07 17:42       ` Stefano Brivio
2023-07-10  7:45         ` David Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230627025429.2209702-11-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=crosa@redhat.com \
    --cc=jarichte@redhat.com \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).