test: make the testsuite passive rather than active
Let the image be responsible for running its own test, and simply listen for the output from the testsuite. Hook this up with a standard f30 image that contains a simple boot test case, using systemctl to verify that all services started correctly. This replaces the old web-server test, giving similar functionality. The reason for the change is twofold: this way the tests are fully specificed in the pipeline, so easier to reproduce. Moreover, this is less intrusive, as the test does not require network support in the image. Signed-off-by: Tom Gundersen <teg@jklm.no>
This commit is contained in:
parent
e14b93b06e
commit
a41ce99521
6 changed files with 52 additions and 97 deletions
|
|
@ -9,13 +9,8 @@ from test.integration_tests.config import *
|
|||
logging.basicConfig(level=logging.getLevelName(os.environ.get("TESTS_LOGLEVEL", "INFO")))
|
||||
|
||||
|
||||
def test_web_server_with_curl():
|
||||
cmd = ["curl", "-s", "http://127.0.0.1:8888/index"]
|
||||
logging.info(f"Running curl: {cmd}")
|
||||
curl = subprocess.run(cmd, capture_output=True)
|
||||
logging.info(f"Curl returned: code={curl.returncode}, stdout={curl.stdout.decode()}, stderr={curl.stderr.decode()}")
|
||||
assert curl.returncode == 0
|
||||
assert curl.stdout.decode("utf-8").strip() == "hello, world!"
|
||||
def test_is_system_running(result):
|
||||
assert result.strip() == "running"
|
||||
|
||||
|
||||
def test_timezone(extract_dir):
|
||||
|
|
@ -43,11 +38,11 @@ if __name__ == '__main__':
|
|||
logging.info(f"Using {OUTPUT_DIR} for output images storage.")
|
||||
logging.info(f"Using {OSBUILD} for building images.")
|
||||
|
||||
web_server = IntegrationTestCase(
|
||||
name="web-server",
|
||||
pipeline="web-server.json",
|
||||
output_image="web-server.qcow2",
|
||||
test_cases=[test_web_server_with_curl],
|
||||
f30_boot = IntegrationTestCase(
|
||||
name="f30-boot",
|
||||
pipeline="f30-boot.json",
|
||||
output_image="f30-boot.qcow2",
|
||||
test_cases=[test_is_system_running],
|
||||
type=IntegrationTestType.BOOT_WITH_QEMU
|
||||
)
|
||||
timezone = IntegrationTestCase(
|
||||
|
|
@ -65,7 +60,7 @@ if __name__ == '__main__':
|
|||
type=IntegrationTestType.EXTRACT
|
||||
)
|
||||
|
||||
cases = [web_server, timezone, firewall]
|
||||
cases = [f30_boot, timezone, firewall]
|
||||
|
||||
if args.list:
|
||||
print("Available test cases:")
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from .config import *
|
||||
|
||||
|
||||
def evaluate_test(test, name=None):
|
||||
def evaluate_test(test, arg=None, name=None):
|
||||
try:
|
||||
test()
|
||||
test(arg)
|
||||
print(f"{RESET}{BOLD}{name or test.__name__}: Success{RESET}")
|
||||
except AssertionError as e:
|
||||
print(f"{RESET}{BOLD}{name or test.__name__}: {RESET}{RED}Fail{RESET}")
|
||||
|
|
|
|||
|
|
@ -6,19 +6,14 @@ import time
|
|||
from .config import *
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def boot_image(file_name: str):
|
||||
def run_image(file_name: str):
|
||||
acceleration = ["-accel", "kvm:hvf:tcg"]
|
||||
network = ["-net", "nic,model=rtl8139", "-net", "user,hostfwd=tcp::8888-:8888"]
|
||||
cmd = ["qemu-system-x86_64", "-nographic", "-m", "1024", "-snapshot"] + \
|
||||
acceleration + [f"{OUTPUT_DIR}/{file_name}"] + network
|
||||
silence = ["-nographic", "-monitor", "none", "-serial", "none"]
|
||||
serial = ["-chardev", "stdio,id=stdio", "-device", "virtio-serial", "-device", "virtserialport,chardev=stdio"]
|
||||
cmd = ["qemu-system-x86_64", "-m", "1024", "-snapshot"] + \
|
||||
acceleration + silence + serial + [f"{OUTPUT_DIR}/{file_name}"]
|
||||
logging.info(f"Booting image: {cmd}")
|
||||
vm = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
try:
|
||||
time.sleep(EXPECTED_TIME_TO_BOOT)
|
||||
yield None
|
||||
finally:
|
||||
vm.kill()
|
||||
return subprocess.run(cmd, capture_output=True, timeout=EXPECTED_TIME_TO_BOOT, encoding="utf-8", check=True)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from typing import List, Callable, Any
|
|||
|
||||
from . import evaluate_test, rel_path
|
||||
from .build import run_osbuild
|
||||
from .run import boot_image, extract_image
|
||||
from .run import run_image, extract_image
|
||||
|
||||
|
||||
class IntegrationTestType(Enum):
|
||||
|
|
@ -23,16 +23,16 @@ class IntegrationTestCase:
|
|||
def run(self):
|
||||
run_osbuild(rel_path(f"pipelines/{self.pipeline}"))
|
||||
if self.type == IntegrationTestType.BOOT_WITH_QEMU:
|
||||
self.boot_and_run()
|
||||
self.run_and_test()
|
||||
else:
|
||||
self.extract_and_run()
|
||||
self.extract_and_test()
|
||||
|
||||
def boot_and_run(self):
|
||||
with boot_image(self.output_image):
|
||||
for test in self.test_cases:
|
||||
evaluate_test(test)
|
||||
def run_and_test(self):
|
||||
r = run_image(self.output_image)
|
||||
for test in self.test_cases:
|
||||
evaluate_test(test, r.stdout)
|
||||
|
||||
def extract_and_run(self):
|
||||
def extract_and_test(self):
|
||||
with extract_image(self.output_image) as fstree:
|
||||
for test in self.test_cases:
|
||||
evaluate_test(lambda: test(fstree), name=test.__name__)
|
||||
|
|
|
|||
106
test/pipelines/f30-boot.json
Normal file
106
test/pipelines/f30-boot.json
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
"name": "f30-boot",
|
||||
"build": {
|
||||
"name": "f30-build",
|
||||
"stages": [
|
||||
{
|
||||
"name": "org.osbuild.dnf",
|
||||
"options": {
|
||||
"releasever": "30",
|
||||
"install_weak_deps": false,
|
||||
"repos": {
|
||||
"fedora": {
|
||||
"name": "Fedora",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch",
|
||||
"gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch"
|
||||
}
|
||||
},
|
||||
"packages": [
|
||||
"dnf",
|
||||
"e2fsprogs",
|
||||
"policycoreutils",
|
||||
"qemu-img",
|
||||
"systemd"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "org.osbuild.dnf",
|
||||
"options": {
|
||||
"releasever": "30",
|
||||
"install_weak_deps": true,
|
||||
"repos": {
|
||||
"fedora": {
|
||||
"name": "Fedora",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch",
|
||||
"gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch"
|
||||
}
|
||||
},
|
||||
"packages": [
|
||||
"@Core",
|
||||
"chrony",
|
||||
"kernel",
|
||||
"selinux-policy-targeted",
|
||||
"grub2-pc",
|
||||
"spice-vdagent",
|
||||
"qemu-guest-agent",
|
||||
"xen-libs",
|
||||
"langpacks-en"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.locale",
|
||||
"options": {
|
||||
"language": "en_US"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.fstab",
|
||||
"options": {
|
||||
"filesystems": [
|
||||
{
|
||||
"uuid": "76a22bf4-f153-4541-b6c7-0332c0dfaeac",
|
||||
"vfs_type": "ext4",
|
||||
"path": "/",
|
||||
"freq": "1",
|
||||
"passno": "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.grub2",
|
||||
"options": {
|
||||
"root_fs_uuid": "76a22bf4-f153-4541-b6c7-0332c0dfaeac",
|
||||
"kernel_opts": "ro biosdevname=0 net.ifnames=0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.test",
|
||||
"options": {
|
||||
"script": "/usr/bin/systemctl is-system-running --wait"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.selinux",
|
||||
"options": {
|
||||
"file_contexts": "etc/selinux/targeted/contexts/files/file_contexts"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.fix-bls"
|
||||
}
|
||||
],
|
||||
"assembler":
|
||||
{
|
||||
"name": "org.osbuild.qcow2",
|
||||
"options": {
|
||||
"filename": "f30-boot.qcow2",
|
||||
"root_fs_uuid": "76a22bf4-f153-4541-b6c7-0332c0dfaeac"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
{
|
||||
"name": "all",
|
||||
"stages": [
|
||||
{
|
||||
"name": "org.osbuild.dnf",
|
||||
"options": {
|
||||
"releasever": "30",
|
||||
"repos": {
|
||||
"fedora": {
|
||||
"name": "Fedora",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch",
|
||||
"gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch"
|
||||
}
|
||||
},
|
||||
"packages": [
|
||||
"@Core",
|
||||
"selinux-policy-targeted",
|
||||
"grub2-pc"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.script",
|
||||
"options": {
|
||||
"script": "echo root | passwd --stdin root; echo 'SELINUX=disabled' > /etc/selinux/config;"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.script",
|
||||
"options": {
|
||||
"script": "mkdir -p /var/web; echo 'hello, world!' > /var/web/index; echo -e \"[Unit]\\nDescription=Testing web server\\nAfter=network.target\\n\\n[Service]\\nType=simple\\nExecStart=python3 -m http.server 8888\\nWorkingDirectory=/var/web/\\n\\n[Install]\\nWantedBy=multi-user.target\" > /etc/systemd/system/web-server.service;"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.systemd",
|
||||
"options": {
|
||||
"enabled_services": [
|
||||
"NetworkManager",
|
||||
"web-server"
|
||||
],
|
||||
"disabled_services": [
|
||||
"firewalld"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "org.osbuild.grub2",
|
||||
"options": {
|
||||
"root_fs_uuid": "76a22bf4-f153-4541-b6c7-0332c0dfaeac",
|
||||
"kernel_opts": "rw"
|
||||
}
|
||||
}
|
||||
],
|
||||
"assembler": {
|
||||
"name": "org.osbuild.qcow2",
|
||||
"options": {
|
||||
"filename": "web-server.qcow2",
|
||||
"root_fs_uuid": "76a22bf4-f153-4541-b6c7-0332c0dfaeac"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue