From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from atuin.qyliss.net (localhost [IPv6:::1]) by atuin.qyliss.net (Postfix) with ESMTP id 28CAFD425; Fri, 13 Jun 2025 14:05:44 +0000 (UTC) Received: by atuin.qyliss.net (Postfix, from userid 993) id 288EED2B0; Fri, 13 Jun 2025 14:05:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on atuin.qyliss.net X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DMARC_MISSING,RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H2, SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=4.0.1 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) by atuin.qyliss.net (Postfix) with ESMTPS id 54B39D293 for ; Fri, 13 Jun 2025 14:05:26 +0000 (UTC) Received: from phl-compute-07.internal (phl-compute-07.phl.internal [10.202.2.47]) by mailfout.phl.internal (Postfix) with ESMTP id B59131380448; Fri, 13 Jun 2025 10:05:24 -0400 (EDT) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-07.internal (MEProxy); Fri, 13 Jun 2025 10:05:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alyssa.is; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1749823524; x= 1749909924; bh=TyD5aLbasNQa8meDqzJGMHsCDjIyXvO7HZ0/cF/ght4=; b=I 3e8vj0bsHzNmnyiJU5KrvrBRcji8fK2o/YgdidvvHRVLfeDZl3A3af/MKjqBeC+B J/HcEDcjg42h9U6wM8s+dNvz+mnu6wRoPCJOfWGzlCtI2ZfLkFwKIH7y+oPy2c+q BpRQf0MlGGx8oybDMNN1SJpGHQ2wwxyr0ECljbKB8XcUbJOMyH9ul9DRgQM40x7B 9AsDt0npIobsepceqvoViRym6PUC6E6JB52eqVGdpGASAqHzuYtmcu281tEO5tWw asBKh84dMXjkRQ63uN3U+u7fX7CI6ixgboCd7xgjF9nUyzovxOdbGDdQychBAwbd BXZOo32ICz4FRYsbijKDA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1749823524; x=1749909924; bh=T yD5aLbasNQa8meDqzJGMHsCDjIyXvO7HZ0/cF/ght4=; b=fj8uRaA71WXPKvChM sZaKScN2lKOM5+p805m5AGMW8NFRC597zgdC5CkLpqsKxB+WgvOBlWusuQOQH3K+ DjJ9W4CGGgnZqof1RvgM/5X7h52mNIeKwhrQog3fM9plx9yw0PDS1mZra6eYZ0gI aLWUhwcaxww8WavF/x5z82SlmeenaXgmDGYClXACklxZUhIYWbexbSlXU36S7Mb7 Hh9/zj6l4mPfGcK4clbxGiMLFYN3Icqkm39nIHyyz+j903oYnvYRJrGlKrkgqf6u Cx1kN59BiWUItD85d56TPoKpCASZP2H7l/qWyqQPUwbVv0blh0vUkVsEJqn6r4xB 3Magw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtddugddukedugecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvve fufffkofgjfhgggfestdekredtredttdenucfhrhhomheptehlhihsshgrucftohhsshcu oehhihesrghlhihsshgrrdhisheqnecuggftrfgrthhtvghrnhepgeeuieduueekkeeivd etffegkeduhfduvedvledvkefhfeeiteekuddujefffeegnecuvehluhhsthgvrhfuihii vgeptdenucfrrghrrghmpehmrghilhhfrhhomhephhhisegrlhihshhsrgdrihhspdhnsg gprhgtphhtthhopedvpdhmohguvgepshhmthhpohhuthdprhgtphhtthhopeguvghvvghl sehsphgvtghtrhhumhdqohhsrdhorhhgpdhrtghpthhtohephihukhgrseihuhhkrgdrug gvvh X-ME-Proxy: Feedback-ID: i12284293:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 13 Jun 2025 10:05:24 -0400 (EDT) Received: by sf.qyliss.net (Postfix, from userid 1000) id DAFD2245D670C; Fri, 13 Jun 2025 16:05:20 +0200 (CEST) From: Alyssa Ross To: devel@spectrum-os.org Subject: [PATCH 7/8] release/checks/integration: extract library Date: Fri, 13 Jun 2025 16:05:07 +0200 Message-ID: <20250613140508.76998-8-hi@alyssa.is> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250613140508.76998-1-hi@alyssa.is> References: <20250613140508.76998-1-hi@alyssa.is> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: ICL3FAAQDQTDPQNRVQGNTZSOIKSSNP3J X-Message-ID-Hash: ICL3FAAQDQTDPQNRVQGNTZSOIKSSNP3J X-MailFrom: hi@alyssa.is X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-devel.spectrum-os.org-0; header-match-devel.spectrum-os.org-1; header-match-devel.spectrum-os.org-2; header-match-devel.spectrum-os.org-3; header-match-devel.spectrum-os.org-4; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Yureka X-Mailman-Version: 3.3.9 Precedence: list List-Id: Patches and low-level development discussion Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: This will ease writing more tests. The drain stuff could probably also be extracted, but the second test I'm currently writing won't use it, so I'm leaving it for now. Signed-off-by: Alyssa Ross --- .../integration/{networking.c => lib.c} | 139 +---------- release/checks/integration/lib.h | 16 ++ release/checks/integration/meson.build | 4 +- release/checks/integration/networking.c | 216 +----------------- 4 files changed, 26 insertions(+), 349 deletions(-) copy release/checks/integration/{networking.c => lib.c} (61%) create mode 100644 release/checks/integration/lib.h diff --git a/release/checks/integration/networking.c b/release/checks/integration/lib.c similarity index 61% copy from release/checks/integration/networking.c copy to release/checks/integration/lib.c index 7331c4a..b0b4507 100644 --- a/release/checks/integration/networking.c +++ b/release/checks/integration/lib.c @@ -1,20 +1,15 @@ // SPDX-License-Identifier: EUPL-1.2+ // SPDX-FileCopyrightText: 2025 Alyssa Ross -#include -#include +#include "lib.h" + #include #include -#include #include #include #include #include -#include -#include - -#include #include #include #include @@ -38,31 +33,6 @@ static void exit_on_sigchld(void) exit(EXIT_FAILURE); } -static void *drain(void *arg) -{ - int c; - - while ((c = fgetc((FILE *)arg)) != EOF) - fputc(c, stderr); - - if (ferror((FILE *)arg)) - return (void *)(intptr_t)errno; - - return nullptr; -} - -static pthread_t start_drain(FILE *console) -{ - pthread_t thread; - int e; - - if (!(e = pthread_create(&thread, nullptr, drain, console))) - return thread; - - fprintf(stderr, "pthread_create: %s\n", strerror(e)); - exit(EXIT_FAILURE); -} - static char *make_tmp_dir(void) { char *dir, *run; @@ -81,48 +51,6 @@ static char *make_tmp_dir(void) return dir; } -static int setup_server(void) -{ - int fd; - struct ifreq ifr; - - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_port = htons(1234), - .sin_addr = { .s_addr = htonl(INADDR_LOOPBACK) }, - }; - - sprintf(ifr.ifr_name, "lo"); - - if ((fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0)) == -1) { - perror("socket"); - exit(EXIT_FAILURE); - } - - if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) { - perror("SIOCGIFFLAGS"); - exit(EXIT_FAILURE); - } - - ifr.ifr_flags |= IFF_UP; - if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) { - perror("SIOCSIFFLAGS"); - exit(EXIT_FAILURE); - } - - if (bind(fd, &addr, sizeof addr) == -1) { - perror("bind"); - exit(EXIT_FAILURE); - } - - if (listen(fd, 1) == -1) { - perror("listen"); - exit(EXIT_FAILURE); - } - - return fd; -} - static int setup_unix(const char *path) { int r, fd; @@ -176,15 +104,7 @@ static void wait_for_prompt(FILE *console) exit(EXIT_FAILURE); } -struct config { - const char *run_qemu; - - struct { - const char *efi, *img, *user_data; - } drives; -}; - -static FILE *start_qemu(struct config c) +FILE *start_qemu(struct config c) { FILE *console; struct utsname u; @@ -259,36 +179,6 @@ static FILE *start_qemu(struct config c) return console; } -static void expect_connection(int listener) -{ - int conn_fd; - FILE *conn; - char msg[7]; - size_t len; - - fputs("waiting for server connection\n", stderr); - if ((conn_fd = accept(listener, nullptr, nullptr)) == -1) { - perror("accept"); - exit(EXIT_FAILURE); - } - fputs("accepted connection!\n", stderr); - if (!(conn = fdopen(conn_fd, "r"))) { - perror("fdopen(server connection)"); - exit(EXIT_FAILURE); - } - - len = fread(msg, 1, sizeof msg, conn); - if (len != 6 || memcmp("hello\n", msg, 6)) { - if (ferror(conn)) - perror("fread(server connection)"); - else - fprintf(stderr, "unexpected connection data: %.*s", - (int)len, msg); - exit(EXIT_FAILURE); - } - fclose(conn); -} - int main(int argc, char *argv[]) { exit_on_sigchld(); @@ -323,26 +213,5 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - int server = setup_server(); - - FILE *console = start_qemu(c); - - if (fputs("set -euxo pipefail\n" - "mkdir /run/mnt\n" - "mount \"$(findfs UUID=a7834806-2f82-4faf-8ac4-4f8fd8a474ca)\" /run/mnt\n" - "s6-rc -bu change vmm-env\n" - "vm-import user /run/mnt/vms\n" - "vm-start user.nc\n" - "tail -Fc +0 /run/log/current /run/user.nc.log\r\n", - console) == EOF) { - fputs("error writing to console\n", stderr); - exit(EXIT_FAILURE); - } - if (fflush(console) == EOF) { - perror("fflush"); - exit(EXIT_FAILURE); - } - start_drain(console); - - expect_connection(server); + test(c); } diff --git a/release/checks/integration/lib.h b/release/checks/integration/lib.h new file mode 100644 index 0000000..959573d --- /dev/null +++ b/release/checks/integration/lib.h @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: EUPL-1.2+ +// SPDX-FileCopyrightText: 2025 Alyssa Ross + +#include + +struct config { + const char *run_qemu; + + struct { + const char *efi, *img, *user_data; + } drives; +}; + +extern void test(struct config); + +FILE *start_qemu(struct config config); diff --git a/release/checks/integration/meson.build b/release/checks/integration/meson.build index 3f273b4..7edc314 100644 --- a/release/checks/integration/meson.build +++ b/release/checks/integration/meson.build @@ -7,7 +7,9 @@ project('spectrum-integration-tests', 'c', add_project_arguments('-D_GNU_SOURCE', language : 'c') -test('networking', executable('networking', 'networking.c'), +lib = static_library('spectrum-integration-test', 'lib.c') + +test('networking', executable('networking', 'networking.c', link_with : lib), args : [ find_program('../../../scripts/run-qemu.sh'), get_option('efi'), diff --git a/release/checks/integration/networking.c b/release/checks/integration/networking.c index 7331c4a..f550edc 100644 --- a/release/checks/integration/networking.c +++ b/release/checks/integration/networking.c @@ -1,42 +1,18 @@ // SPDX-License-Identifier: EUPL-1.2+ // SPDX-FileCopyrightText: 2025 Alyssa Ross +#include "lib.h" + #include #include -#include -#include #include -#include #include #include -#include #include #include #include -#include -#include -#include -#include - -static void chld_handler(int) -{ - exit(EXIT_FAILURE); -} - -static void exit_on_sigchld(void) -{ - struct sigaction sa = { - .sa_handler = chld_handler, - .sa_flags = SA_NOCLDSTOP, - }; - if (!sigaction(SIGCHLD, &sa, nullptr)) - return; - - perror("sigaction"); - exit(EXIT_FAILURE); -} static void *drain(void *arg) { @@ -63,24 +39,6 @@ static pthread_t start_drain(FILE *console) exit(EXIT_FAILURE); } -static char *make_tmp_dir(void) -{ - char *dir, *run; - if (!(run = secure_getenv("XDG_RUNTIME_DIR"))) { - fputs("warning: XDG_RUNTIME_DIR unset\n", stderr); - run = "/tmp"; - } - if (asprintf(&dir, "%s/spectrum-test.XXXXXX", run) == -1) { - perror("asprintf"); - exit(EXIT_FAILURE); - } - if (!mkdtemp(dir)) { - perror("mkdtemp"); - exit(EXIT_FAILURE); - } - return dir; -} - static int setup_server(void) { int fd; @@ -123,142 +81,6 @@ static int setup_server(void) return fd; } -static int setup_unix(const char *path) -{ - int r, fd; - struct sockaddr_un addr = { .sun_family = AF_UNIX }; - - r = snprintf(addr.sun_path, sizeof addr.sun_path, "%s", path); - if (r >= sizeof addr.sun_path) { - fputs("XDG_RUNTIME_DIR too long\n", stderr); - exit(EXIT_FAILURE); - } - - if (r < 0) { - fputs("snprintf error\n", stderr); - exit(EXIT_FAILURE); - } - - if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0)) == -1) { - perror("socket"); - exit(EXIT_FAILURE); - } - - if (bind(fd, &addr, sizeof addr) == -1) { - perror("bind"); - exit(EXIT_FAILURE); - } - - if (listen(fd, 1) == -1) { - perror("listen"); - exit(EXIT_FAILURE); - } - - return fd; -} - -static void wait_for_prompt(FILE *console) -{ - char *needle = "~ # "; - size_t i = 0; - int c; - - fputs("waiting for character\n", stderr); - - while ((c = fgetc(console)) != EOF) { - fputc(c, stderr); - i = c == needle[i] ? i + 1 : 0; - if (!needle[i]) - return; - } - - fputs("unexpected EOF from console\n", stderr); - exit(EXIT_FAILURE); -} - -struct config { - const char *run_qemu; - - struct { - const char *efi, *img, *user_data; - } drives; -}; - -static FILE *start_qemu(struct config c) -{ - FILE *console; - struct utsname u; - int console_listener, console_conn; - char *arch, *args[] = { - (char *)c.run_qemu, - "-drive", nullptr, - "-drive", nullptr, - "-drive", nullptr, - "-m", "4G", - "-nodefaults", - "-machine", "virtualization=on", - "-cpu", "max", - "-device", "virtio-keyboard", - "-device", "virtio-mouse", - "-device", "virtio-gpu", - "-netdev", "user,id=net0", - "-device", "e1000e,netdev=net0", - "-monitor", "vc", - "-vga", "none", - "-smbios", "type=11,value=io.systemd.stub.kernel-cmdline-extra=console=ttyS0", - "-serial", "unix:console", - nullptr, - }; - char **efi_arg = &args[2], **img_arg = &args[4], - **user_data_arg = &args[6]; - - if (!(arch = getenv("ARCH"))) { - uname(&u); - arch = u.machine; - } - if (strcmp(arch, "x86_64")) - args[sizeof args / sizeof *args - 3] = nullptr; - - console_listener = setup_unix("console"); - - switch (fork()) { - case -1: - perror("fork"); - exit(EXIT_FAILURE); - case 0: - if (prctl(PR_SET_PDEATHSIG, SIGTERM) == -1) { - perror("prctl"); - exit(EXIT_FAILURE); - } - - if (asprintf(efi_arg, "file=%s,format=raw,if=pflash,readonly=true", c.drives.efi) == -1 || - asprintf(img_arg, "file=%s,format=raw,if=virtio,readonly=true", c.drives.img) == -1 || - asprintf(user_data_arg, "file=%s,format=raw,if=virtio,readonly=true", c.drives.user_data) == -1) { - perror("asprintf"); - exit(EXIT_FAILURE); - } - - execv(c.run_qemu, args); - perror("execv"); - exit(EXIT_FAILURE); - } - - if ((console_conn = accept(console_listener, nullptr, nullptr)) == -1) { - perror("accept"); - exit(EXIT_FAILURE); - } - if (!(console = fdopen(console_conn, "a+"))) { - perror("fdopen"); - exit(EXIT_FAILURE); - } - - fputs("waiting for console prompt\n", stderr); - - wait_for_prompt(console); - - return console; -} - static void expect_connection(int listener) { int conn_fd; @@ -289,40 +111,8 @@ static void expect_connection(int listener) fclose(conn); } -int main(int argc, char *argv[]) +void test(struct config c) { - exit_on_sigchld(); - - if (argc != 5) { - fputs("Usage: test efi spectrum user_data\n", stderr); - exit(EXIT_FAILURE); - } - - struct config c = { - .run_qemu = argv[1], - .drives = { - .efi = argv[2], - .img = argv[3], - .user_data = argv[4], - }, - }; - - if (strchr(c.drives.efi, ',') || strchr(c.drives.img, ',') || - strchr(c.drives.user_data, ',')) { - fputs("arguments contain commas\n", stderr); - exit(EXIT_FAILURE); - } - - if (unshare(CLONE_NEWUSER|CLONE_NEWNET) == -1) { - perror("unshare"); - exit(EXIT_FAILURE); - } - - if (chdir(make_tmp_dir()) == -1) { - perror("chdir"); - exit(EXIT_FAILURE); - } - int server = setup_server(); FILE *console = start_qemu(c); -- 2.49.0