From 9ad73681fac2e44ef05725a71bee0abc70663dc6 Mon Sep 17 00:00:00 2001 From: iximeow Date: Tue, 22 Oct 2024 23:21:49 +0000 Subject: [PATCH] phd: gate OS-specific tests, make others more OS-agnostic (#799) some smoketests instigated a graceful reboot by sending `reboot\n` to the serial console, but Windows guests are rewarded (via Cygwin) with ``` bash: reboot: command not found ``` as of #785 there is now a TestVm helper `graceful_reboot` that does this in whatever way the guest adapter desires, so use that instead. unfortunately `graceful_reboot` is only mostly right for Windows guests, so fix that here too: `shutdown` immediately terminates the cmd.exe session, at which point the SAC redraws the previous screen, which happens to have all the sigils we look for to detect that Windows has freshly booted. we then log back into the imminently-shutdown Windows, shutdown takes effect, and PHD becomes fully desynchronized from the guest state. so, look for "BdsDxe: loading " as an outside-the-guest-OS sigil that tells us we're watching a fresh boot. this comes from OVMF, so a booted guest will have clobbered the message and not know to redraw it even if it seeks to recreate a previous display. other tests depend on Linux-specific features like `efivarfs` or `mount -o ro`, so skip them on non-Linux guests. --- phd-tests/framework/src/guest_os/mod.rs | 24 +++++++++++++++++++++ phd-tests/framework/src/guest_os/windows.rs | 16 ++++++++++++++ phd-tests/tests/src/boot_order.rs | 12 +++++++++++ phd-tests/tests/src/crucible/smoke.rs | 5 +---- phd-tests/tests/src/disk.rs | 3 +++ phd-tests/tests/src/smoke.rs | 5 +---- 6 files changed, 57 insertions(+), 8 deletions(-) diff --git a/phd-tests/framework/src/guest_os/mod.rs b/phd-tests/framework/src/guest_os/mod.rs index 7359deebd..246369a0f 100644 --- a/phd-tests/framework/src/guest_os/mod.rs +++ b/phd-tests/framework/src/guest_os/mod.rs @@ -99,6 +99,30 @@ pub enum GuestOsKind { WindowsServer2022, } +impl GuestOsKind { + pub fn is_linux(&self) -> bool { + match self { + GuestOsKind::Alpine + | GuestOsKind::Debian11NoCloud + | GuestOsKind::Ubuntu2204 => true, + GuestOsKind::WindowsServer2016 + | GuestOsKind::WindowsServer2019 + | GuestOsKind::WindowsServer2022 => false, + } + } + + pub fn is_windows(&self) -> bool { + match self { + GuestOsKind::WindowsServer2016 + | GuestOsKind::WindowsServer2019 + | GuestOsKind::WindowsServer2022 => true, + GuestOsKind::Alpine + | GuestOsKind::Debian11NoCloud + | GuestOsKind::Ubuntu2204 => false, + } + } +} + impl FromStr for GuestOsKind { type Err = std::io::Error; diff --git a/phd-tests/framework/src/guest_os/windows.rs b/phd-tests/framework/src/guest_os/windows.rs index 2c8f4d226..8da922532 100644 --- a/phd-tests/framework/src/guest_os/windows.rs +++ b/phd-tests/framework/src/guest_os/windows.rs @@ -37,6 +37,22 @@ pub(super) fn get_login_sequence_for<'a>( )); let mut commands = vec![ + // Look for `BdsDxe:` as a sign that we're actually seeing a fresh boot. + // This is not terribly important in the case of a first boot, but in a + // case such as logging out and waiting for reboot, exiting a cmd.exe + // session causes Windows to redraw its previous screen - everything + // past `Computer is booting, ...` below. + // + // A test that tries to boot and wait for a new login sequence would + // then incorrectly identify the already-booted VM as the freshly-booted + // OS it was waiting for, log in again, and at some point later finally + // actually reboot. + // + // At least on Windows Server 2022, there is an XML prelude that is + // printed to COM1 that we could look for here, but check for `BdsDxe: ` + // instead as that comes from OVMF and will be consistent regardless of + // guest OS version. + CommandSequenceEntry::wait_for("BdsDxe: loading "), CommandSequenceEntry::wait_for( "Computer is booting, SAC started and initialized.", ), diff --git a/phd-tests/tests/src/boot_order.rs b/phd-tests/tests/src/boot_order.rs index 89f640390..0e5af8f2b 100644 --- a/phd-tests/tests/src/boot_order.rs +++ b/phd-tests/tests/src/boot_order.rs @@ -98,6 +98,9 @@ async fn configurable_boot_order(ctx: &Framework) { // We haven't specified a boot order. So, we'll expect that we boot to the // lower-numbered PCI device (4) and end up in Alpine 3.20. let mut vm = ctx.spawn_vm(&cfg, None).await?; + if !vm.guest_os_kind().is_linux() { + phd_skip!("boot order tests require efivarfs to manipulate UEFI vars"); + } vm.launch().await?; vm.wait_to_boot().await?; @@ -162,6 +165,9 @@ async fn unbootable_disk_skipped(ctx: &Framework) { cfg.boot_order(vec!["unbootable", "boot-disk"]); let mut vm = ctx.spawn_vm(&cfg, None).await?; + if !vm.guest_os_kind().is_linux() { + phd_skip!("boot order tests require efivarfs to manipulate UEFI vars"); + } vm.launch().await?; vm.wait_to_boot().await?; @@ -279,6 +285,9 @@ async fn guest_can_adjust_boot_order(ctx: &Framework) { cfg.boot_order(vec!["boot-disk", "unbootable"]); let mut vm = ctx.spawn_vm(&cfg, None).await?; + if !vm.guest_os_kind().is_linux() { + phd_skip!("boot order tests require efivarfs to manipulate UEFI vars"); + } vm.launch().await?; vm.wait_to_boot().await?; @@ -446,6 +455,9 @@ async fn boot_order_source_priority(ctx: &Framework) { cfg.clear_boot_order(); let mut vm_no_bootorder = ctx.spawn_vm(&cfg, None).await?; + if !vm_no_bootorder.guest_os_kind().is_linux() { + phd_skip!("boot order tests require efivarfs to manipulate UEFI vars"); + } vm_no_bootorder.launch().await?; vm_no_bootorder.wait_to_boot().await?; diff --git a/phd-tests/tests/src/crucible/smoke.rs b/phd-tests/tests/src/crucible/smoke.rs index 2955d8bdc..a27134579 100644 --- a/phd-tests/tests/src/crucible/smoke.rs +++ b/phd-tests/tests/src/crucible/smoke.rs @@ -37,10 +37,7 @@ async fn guest_reboot_test(ctx: &Framework) { vm.launch().await?; vm.wait_to_boot().await?; - // Don't use `run_shell_command` because the guest won't echo another prompt - // after this. - vm.send_serial_str("reboot\n").await?; - vm.wait_to_boot().await?; + vm.graceful_reboot().await?; } #[phd_testcase] diff --git a/phd-tests/tests/src/disk.rs b/phd-tests/tests/src/disk.rs index 1db141c90..aac22a3f3 100644 --- a/phd-tests/tests/src/disk.rs +++ b/phd-tests/tests/src/disk.rs @@ -25,6 +25,9 @@ async fn in_memory_backend_smoke_test(ctx: &Framework) { ); let mut vm = ctx.spawn_vm(&cfg, None).await?; + if vm.guest_os_kind().is_windows() { + phd_skip!("this test uses mount options not supported by Cygwin"); + } vm.launch().await?; vm.wait_to_boot().await?; diff --git a/phd-tests/tests/src/smoke.rs b/phd-tests/tests/src/smoke.rs index 5537e19eb..592145b60 100644 --- a/phd-tests/tests/src/smoke.rs +++ b/phd-tests/tests/src/smoke.rs @@ -30,10 +30,7 @@ async fn guest_reboot_test(ctx: &Framework) { vm.launch().await?; vm.wait_to_boot().await?; - // Don't use `run_shell_command` because the guest won't echo another prompt - // after this. - vm.send_serial_str("reboot\n").await?; - vm.wait_to_boot().await?; + vm.graceful_reboot().await?; } #[phd_testcase]