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,-hyperv_vbs,+windows,+ubuntu,+freebsd,+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
122        pipeline
123            .new_job(
124                FlowPlatform::host(backend_hint),
125                FlowArch::host(backend_hint),
126                "build vmm test dependencies",
127            )
128            .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_versions::Request {})
129            .dep_on(
130                |_| flowey_lib_hvlite::_jobs::cfg_hvlite_reposource::Params {
131                    hvlite_repo_source: openvmm_repo.clone(),
132                },
133            )
134            .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_common::Params {
135                local_only: Some(flowey_lib_hvlite::_jobs::cfg_common::LocalOnlyParams {
136                    interactive: true,
137                    auto_install: install_missing_deps,
138                    force_nuget_mono: false,
139                    external_nuget_auth: false,
140                    ignore_rust_version: true,
141                }),
142                verbose: ReadVar::from_static(verbose),
143                locked: false,
144                deny_warnings: false,
145            })
146            .dep_on(
147                |ctx| flowey_lib_hvlite::_jobs::local_build_and_run_nextest_vmm_tests::Params {
148                    target,
149                    test_content_dir: dir,
150                    selections: if let Some(filter) = filter {
151                        VmmTestSelections::Custom {
152                            filter,
153                            artifacts,
154                            // TODO: add a way to manually specify these
155                            // For now, just build and install everything.
156                            build: Default::default(),
157                            deps: match target_os {
158                                target_lexicon::OperatingSystem::Windows => {
159                                    VmmTestsDepSelections::Windows {
160                                        hyperv: true,
161                                        whp: true,
162                                        hardware_isolation: true,
163                                    }
164                                }
165                                target_lexicon::OperatingSystem::Linux => {
166                                    VmmTestsDepSelections::Linux
167                                }
168                                _ => unreachable!(),
169                            },
170                        }
171                    } else {
172                        VmmTestSelections::Flags(flags.unwrap_or_default())
173                    },
174                    unstable_whp,
175                    release,
176                    build_only,
177                    copy_extras,
178                    done: ctx.new_done_handle(),
179                },
180            )
181            .finish();
182
183        Ok(pipeline)
184    }
185}