flowey_hvlite/pipelines/
vmm_tests.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use flowey::node::prelude::ReadVar;
5use flowey::pipeline::prelude::*;
6use flowey_lib_hvlite::_jobs::local_build_and_run_nextest_vmm_tests::VmmTestSelectionFlags;
7use flowey_lib_hvlite::_jobs::local_build_and_run_nextest_vmm_tests::VmmTestSelections;
8use flowey_lib_hvlite::install_vmm_tests_deps::VmmTestsDepSelections;
9use flowey_lib_hvlite::run_cargo_build::common::CommonTriple;
10use std::path::PathBuf;
11use vmm_test_images::KnownTestArtifacts;
12
13#[derive(clap::ValueEnum, Copy, Clone)]
14pub enum VmmTestTargetCli {
15    /// Windows Aarch64
16    WindowsAarch64,
17    /// Windows X64
18    WindowsX64,
19    /// Linux X64
20    LinuxX64,
21}
22
23/// Build everything needed and run the VMM tests
24#[derive(clap::Args)]
25pub struct VmmTestsCli {
26    /// Specify what target to build the VMM tests for
27    ///
28    /// If not specified, defaults to the current host target.
29    #[clap(long)]
30    target: Option<VmmTestTargetCli>,
31
32    /// Directory for the output artifacts
33    #[clap(long)]
34    dir: PathBuf,
35
36    /// Custom test filter
37    #[clap(long, conflicts_with("flags"))]
38    filter: Option<String>,
39    /// Custom list of artifacts to download
40    #[clap(long, conflicts_with("flags"), requires("filter"))]
41    artifacts: Vec<KnownTestArtifacts>,
42    /// Flags used to generate the VMM test filter
43    ///
44    /// Syntax: `--flags=<+|-><flag>,..`
45    ///
46    /// Available flags with default values:
47    ///
48    /// `-tdx,-snp,-hyperv_vbs,+windows,+ubuntu,+freebsd,+linux,+openhcl,+openvmm,+hyperv,+uefi,+pcat,+tmk,+guest_test_uefi`
49    // TODO: Automatically generate the list of possible flags
50    #[clap(long)]
51    flags: Option<VmmTestSelectionFlags>,
52
53    /// pass `--verbose` to cargo
54    #[clap(long)]
55    verbose: bool,
56    /// Automatically install any missing required dependencies.
57    #[clap(long)]
58    install_missing_deps: bool,
59
60    /// Use unstable WHP interfaces
61    #[clap(long)]
62    unstable_whp: bool,
63    /// Release build instead of debug build
64    #[clap(long)]
65    release: bool,
66
67    /// Build only, do not run
68    #[clap(long)]
69    build_only: bool,
70    /// Copy extras to output dir (symbols, etc)
71    #[clap(long)]
72    copy_extras: bool,
73}
74
75impl IntoPipeline for VmmTestsCli {
76    fn into_pipeline(self, backend_hint: PipelineBackendHint) -> anyhow::Result<Pipeline> {
77        if !matches!(backend_hint, PipelineBackendHint::Local) {
78            anyhow::bail!("vmm-tests is for local use only")
79        }
80
81        let Self {
82            target,
83            dir,
84            filter,
85            artifacts,
86            flags,
87            verbose,
88            install_missing_deps,
89            unstable_whp,
90            release,
91            build_only,
92            copy_extras,
93        } = self;
94
95        let openvmm_repo = flowey_lib_common::git_checkout::RepoSource::ExistingClone(
96            ReadVar::from_static(crate::repo_root()),
97        );
98
99        let mut pipeline = Pipeline::new();
100
101        let target = if let Some(t) = target {
102            t
103        } else {
104            match (
105                FlowArch::host(backend_hint),
106                FlowPlatform::host(backend_hint),
107            ) {
108                (FlowArch::Aarch64, FlowPlatform::Windows) => VmmTestTargetCli::WindowsAarch64,
109                (FlowArch::X86_64, FlowPlatform::Windows) => VmmTestTargetCli::WindowsX64,
110                (FlowArch::X86_64, FlowPlatform::Linux(_)) => VmmTestTargetCli::LinuxX64,
111                _ => anyhow::bail!("unsupported host"),
112            }
113        };
114
115        let target = match target {
116            VmmTestTargetCli::WindowsAarch64 => CommonTriple::AARCH64_WINDOWS_MSVC,
117            VmmTestTargetCli::WindowsX64 => CommonTriple::X86_64_WINDOWS_MSVC,
118            VmmTestTargetCli::LinuxX64 => CommonTriple::X86_64_LINUX_GNU,
119        };
120        let target_os = target.as_triple().operating_system;
121        let target_architecture = target.as_triple().architecture;
122
123        pipeline
124            .new_job(
125                FlowPlatform::host(backend_hint),
126                FlowArch::host(backend_hint),
127                "build vmm test dependencies",
128            )
129            .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_versions::Request {})
130            .dep_on(
131                |_| flowey_lib_hvlite::_jobs::cfg_hvlite_reposource::Params {
132                    hvlite_repo_source: openvmm_repo.clone(),
133                },
134            )
135            .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_common::Params {
136                local_only: Some(flowey_lib_hvlite::_jobs::cfg_common::LocalOnlyParams {
137                    interactive: true,
138                    auto_install: install_missing_deps,
139                    force_nuget_mono: false,
140                    external_nuget_auth: false,
141                    ignore_rust_version: true,
142                }),
143                verbose: ReadVar::from_static(verbose),
144                locked: false,
145                deny_warnings: false,
146            })
147            .dep_on(
148                |ctx| flowey_lib_hvlite::_jobs::local_build_and_run_nextest_vmm_tests::Params {
149                    target,
150                    test_content_dir: dir,
151                    selections: if let Some(filter) = filter {
152                        VmmTestSelections::Custom {
153                            filter,
154                            artifacts,
155                            // TODO: add a way to manually specify these
156                            // For now, just build and install everything.
157                            build: Default::default(),
158                            deps: match target_os {
159                                target_lexicon::OperatingSystem::Windows => {
160                                    VmmTestsDepSelections::Windows {
161                                        hyperv: true,
162                                        whp: true,
163                                        // No hardware isolation support on Aarch64, so don't default to needing it when the
164                                        // user specifies a custom filter.
165                                        hardware_isolation: match target_architecture {
166                                            target_lexicon::Architecture::Aarch64(_) => false,
167                                            target_lexicon::Architecture::X86_64 => true,
168                                            _ => panic!(
169                                                "Unhandled architecture: {:?}",
170                                                target_architecture
171                                            ),
172                                        },
173                                    }
174                                }
175                                target_lexicon::OperatingSystem::Linux => {
176                                    VmmTestsDepSelections::Linux
177                                }
178                                _ => unreachable!(),
179                            },
180                        }
181                    } else {
182                        VmmTestSelections::Flags(flags.unwrap_or_default())
183                    },
184                    unstable_whp,
185                    release,
186                    build_only,
187                    copy_extras,
188                    done: ctx.new_done_handle(),
189                },
190            )
191            .finish();
192
193        Ok(pipeline)
194    }
195}