The pxe test for a net device does not fail gracefully when the s390-ccw.img in use was built without support for booting that device.
Add a boot_dev_support check that searches for a known string in the bios image to confirm boot support. If absent, the test is skipped gracefully instead of failing. Also re-enable pxe-test in qtests_s390x, which was accidentally removed by commit 973d97feca93. Signed-off-by: Zhuoying Cai <[email protected]> --- tests/qtest/meson.build | 1 + tests/qtest/pxe-test.c | 84 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index c3593f7530..2cfbdf9b9f 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -292,6 +292,7 @@ qtests_aarch64 = \ 'migration-test'] qtests_s390x = \ + (slirp.found() ? ['pxe-test'] : []) + \ qtests_filter + \ ['boot-serial-test', 'drive_del-test', diff --git a/tests/qtest/pxe-test.c b/tests/qtest/pxe-test.c index e85dec5a4e..8b6015b6cd 100644 --- a/tests/qtest/pxe-test.c +++ b/tests/qtest/pxe-test.c @@ -26,6 +26,7 @@ typedef struct testdef { const char *machine; /* Machine type */ const char *model; /* NIC device model */ const char *extra; /* Any additional parameters */ + bool (*boot_dev_support)(void); /* optional: boot device support check */ } testdef_t; static testdef_t x86_tests[] = { @@ -58,8 +59,79 @@ static testdef_t ppc64_tests_slow[] = { { NULL }, }; +static const char *s390_bios_load(gsize *len) +{ + static char *cached_contents; + static gsize cached_len; + const char *qemu_bin; + g_autofree char *cmd = NULL; + char dir[PATH_MAX]; + char *found = NULL; + char *path = NULL; + FILE *fp; + + if (cached_contents) { + g_test_message("Using cached bios contents"); + goto out; + } + + /* search the qemu binary's data directories for s390-ccw.img */ + qemu_bin = qtest_qemu_binary(NULL); + cmd = g_strdup_printf("%s -L help", qemu_bin); + fp = popen(cmd, "r"); + + if (!fp) { + g_error("Failed to run '%s'", cmd); + } + + while (fgets(dir, sizeof(dir), fp) && !found) { + dir[strcspn(dir, "\n")] = '\0'; + path = g_build_filename(dir, "s390-ccw.img", NULL); + if (g_file_get_contents(path, &cached_contents, &cached_len, NULL)) { + found = path; + } else { + g_free(path); + } + } + pclose(fp); + + if (!found) { + g_error("s390-ccw.img not found"); + } + + g_test_message("Loaded %s", found); + g_free(found); + +out: + *len = cached_len; + return cached_contents; +} + +static bool s390_bios_has_string(const char *needle) +{ + const char *contents; + gsize len; + bool found; + + contents = s390_bios_load(&len); + found = memmem(contents, len, needle, strlen(needle)) != NULL; + + g_test_message("%s %s", needle, found ? "found" : "not found"); + return found; +} + +static bool s390_bios_has_net_ccw(void) +{ + /* + * virtio-net-ccw has always been supported; + * probe for the string it always emits + */ + return s390_bios_has_string("Network boot starting..."); +} + static testdef_t s390x_tests[] = { - { "s390-ccw-virtio", "virtio-net-ccw" }, + { "s390-ccw-virtio", "virtio-net-ccw", + .boot_dev_support = s390_bios_has_net_ccw }, { NULL }, }; @@ -90,6 +162,11 @@ static void test_pxe_ipv4(gconstpointer data) { const testdef_t *test = data; + if (test->boot_dev_support && !test->boot_dev_support()) { + g_test_skip("The bios does not support booting this device"); + return; + } + test_pxe_one(test, false); } @@ -97,6 +174,11 @@ static void test_pxe_ipv6(gconstpointer data) { const testdef_t *test = data; + if (test->boot_dev_support && !test->boot_dev_support()) { + g_test_skip("The bios does not support booting this device"); + return; + } + test_pxe_one(test, true); } -- 2.55.0
