aboutgitcodelistschat:MatrixIRC
diff options
context:
space:
mode:
authorAlice Frosi <afrosi@redhat.com>2022-12-21 15:22:37 +0100
committerAlice Frosi <afrosi@redhat.com>2023-02-15 11:31:46 +0100
commita5ab34509d8a52c37ab6c9c5d5f3501b61bd8d0e (patch)
treef18d38b812a7c263a35d18c22c983019af0374c3
parentb47cde4553f31b033cd3d096552c0a5646cdc88d (diff)
downloadseitan-a5ab34509d8a52c37ab6c9c5d5f3501b61bd8d0e.tar
seitan-a5ab34509d8a52c37ab6c9c5d5f3501b61bd8d0e.tar.gz
seitan-a5ab34509d8a52c37ab6c9c5d5f3501b61bd8d0e.tar.bz2
seitan-a5ab34509d8a52c37ab6c9c5d5f3501b61bd8d0e.tar.lz
seitan-a5ab34509d8a52c37ab6c9c5d5f3501b61bd8d0e.tar.xz
seitan-a5ab34509d8a52c37ab6c9c5d5f3501b61bd8d0e.tar.zst
seitan-a5ab34509d8a52c37ab6c9c5d5f3501b61bd8d0e.zip
integration: create integration tests
Create initial pytest suite for testing seitan and seitan-eater setup. The test suite includes: - 'test_simple' verifies the basic functionalities and the synchronization between seitan and the eater - 'test_restart_seitan' verifies when steitan needs to restart Seitan and eater are deployed in a container to control the environment where they run. Signed-off-by: Alice Frosi <afrosi@redhat.com>
-rw-r--r--Makefile9
-rw-r--r--containerfiles/tests/eater/Containerfile14
-rw-r--r--containerfiles/tests/seitan/Containerfile4
-rw-r--r--requirements.txt3
-rwxr-xr-xtests/integration/seitan_containers.py131
5 files changed, 161 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 4a1b444..526e407 100644
--- a/Makefile
+++ b/Makefile
@@ -33,6 +33,15 @@ numbers.h:
test-unit:
$(MAKE) -C tests/unit
+build-test-images: build seitan seitan-eater
+ $(MAKE) -C tests-utils
+ ./build test.bpf
+ sudo podman build -t test-seitan -f containerfiles/tests/seitan/Containerfile .
+ sudo podman build -t test-eater -f containerfiles/tests/eater/Containerfile .
+
+test-integration:
+ python -m pytest tests/integration/seitan_containers.py
+
transform.h: qemu_filter
./transform.sh qemu_filter
diff --git a/containerfiles/tests/eater/Containerfile b/containerfiles/tests/eater/Containerfile
new file mode 100644
index 0000000..53e5b1c
--- /dev/null
+++ b/containerfiles/tests/eater/Containerfile
@@ -0,0 +1,14 @@
+FROM fedora:37
+
+RUN mkdir -p /var/run/test-filters
+
+COPY ./seitan-eater /usr/bin/seitan-eater
+COPY ./tests-utils/test-syscalls /usr/local/bin/test-syscalls
+# Filter without syscalls
+COPY ./test.bpf /var/run/test-filters/test.bpf
+
+# Make all test filter files reable by all users
+RUN chmod -R 0777 /var/run/test-filters && \
+ chmod 0777 /var/run/test-filters/*
+
+ENTRYPOINT ["/usr/bin/seitan-eater"]
diff --git a/containerfiles/tests/seitan/Containerfile b/containerfiles/tests/seitan/Containerfile
new file mode 100644
index 0000000..e185388
--- /dev/null
+++ b/containerfiles/tests/seitan/Containerfile
@@ -0,0 +1,4 @@
+FROM fedora:37
+
+COPY ./seitan /usr/bin/seitan
+COPY ./tests-utils/test-server /usr/local/bin/test-server
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..759bdd2
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+podman==4.3.0
+pytest==7.2.1
+waiting==1.4.1
diff --git a/tests/integration/seitan_containers.py b/tests/integration/seitan_containers.py
new file mode 100755
index 0000000..a3cff8b
--- /dev/null
+++ b/tests/integration/seitan_containers.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python3
+
+from podman import PodmanClient
+from podman.domain.containers import Container
+from podman import errors
+from waiting import wait, TimeoutExpired
+import pytest
+import time
+
+# The test requires podman root as seitan needs privileged capabilities
+uri = "unix:///run/podman/podman.sock"
+eater_image = "test-eater:latest"
+seitan_image = "test-seitan:latest"
+
+class ContainerConfig:
+ def __init__(self, seitan, eater,
+ exit_code_seitan, exit_code_eater, error_seitan, error_eater,
+ process, proc_args = []):
+ self.client = PodmanClient(base_url=uri)
+ self.exit_code_seitan = exit_code_seitan
+ self.exit_code_eater = exit_code_eater
+ self.error_seitan = error_seitan
+ self.error_eater = error_eater
+
+ # Create eater container
+ self.eater = self.client.containers.run(eater_image,
+ name = eater,
+ detach = True,
+ user = "1000",
+ tty = True,
+ command = ["/usr/bin/seitan-eater",
+ "-i",
+ "/var/run/test-filters/test.bpf",
+ "--",
+ process] + proc_args)
+ res = self.eater.inspect()
+ pid = (res["State"]["Pid"])
+ if not isinstance(pid, int):
+ sys.exit("pid isn't an integer:", pid)
+
+ # Create seitan container
+ self.seitan = self.client.containers.run(seitan_image,
+ name = seitan,
+ detach = True,
+ tty = True,
+ remove = True,
+ pid_mode = "host",
+ network_mode= "host",
+ privileged = True,
+ command = [ "/usr/bin/seitan",
+ "-p", str(pid),
+ # TODO: replace /dev/null with input file
+ "-i", "/dev/null"])
+ def wait_containers_creation(self):
+ self.eater.wait(interval="2s")
+ self.seitan.wait(interval="2s")
+
+ def wait_container_terminate(self):
+ def check_container_status(container: "Container"):
+ if(container.inspect()["State"]["Status"]) == "exited":
+ return True
+ return False
+ wait(lambda: check_container_status(self.eater), timeout_seconds=5)
+
+ def print_logs(self):
+ print("Output seitan:")
+ self.seitan.logs()
+ print("Output eater:")
+ self.eater.logs()
+
+ def check_results(self):
+ self.wait_containers_creation()
+ self.wait_container_terminate()
+ self.print_logs()
+ print("Got:", self.seitan.inspect() ["State"]["ExitCode"], "Expected:", self.exit_code_seitan)
+ assert (self.seitan.inspect() ["State"]["ExitCode"]) == self.exit_code_seitan
+ assert (self.eater.inspect()["State"]["ExitCode"]) == self.exit_code_eater
+ assert (self.seitan.inspect()["State"]["Error"]) == self.error_seitan
+ assert (self.eater.inspect()["State"]["Error"]) == self.error_eater
+
+ def restart_seitan(self):
+ self.seitan.restart()
+
+ def stop_eater(self):
+ self.eater.stop()
+
+def clean_up_containers(containers = []):
+ with PodmanClient(base_url=uri) as client:
+ for c in containers:
+ client.containers.remove(c, force = True)
+
+@pytest.fixture()
+def seitan_container(request):
+ return "seitan_"+request.node.name
+
+@pytest.fixture()
+def eater_container(request):
+ return "eater_"+request.node.name
+
+@pytest.fixture(autouse=True)
+def setup(seitan_container, eater_container):
+ try:
+ clean_up_containers([seitan_container,eater_container])
+ except errors.exceptions.NotFound as e:
+ print("No previous container existing")
+ yield
+ try:
+ print("Delete ", seitan_container, eater_container)
+ clean_up_containers([seitan_container,eater_container])
+ except errors.exceptions.NotFound as e:
+ print("Containers already be removed")
+
+
+def test_simple(seitan_container, eater_container):
+ test = ContainerConfig(seitan=seitan_container, eater=eater_container,
+ exit_code_seitan=0, exit_code_eater=0,
+ error_seitan="", error_eater= "",
+ process = "true")
+ test.check_results()
+
+def test_restart_seitan(seitan_container, eater_container):
+ test = ContainerConfig(seitan=seitan_container, eater=eater_container,
+ exit_code_seitan=0, exit_code_eater=137,
+ error_seitan="", error_eater= "",
+ process = "sleep", proc_args = ["1000"])
+ # Give seitan some time to unblock the eater
+ # TODO: find a better way to detect that sleep has started
+ time.sleep(10)
+ test.restart_seitan()
+ test.stop_eater()
+ test.check_results()