1use anyhow::Context as _;
13use flowey::node::prelude::ReadVar;
14use flowey::pipeline::prelude::*;
15use flowey_lib_hvlite::_jobs::local_build_and_run_nextest_vmm_tests::BuildSelections;
16use flowey_lib_hvlite::_jobs::local_build_and_run_nextest_vmm_tests::VmmTestSelections;
17use flowey_lib_hvlite::common::CommonTriple;
18use flowey_lib_hvlite::install_vmm_tests_deps::VmmTestsDepSelections;
19use flowey_lib_hvlite::install_vmm_tests_deps::VmmTestsDepSelectionsWindows;
20use petri_artifacts_core::ArtifactId;
21use petri_artifacts_core::ArtifactListOutput;
22use std::collections::BTreeMap;
23use std::collections::BTreeSet;
24use std::io::Write as _;
25use std::path::Path;
26use std::path::PathBuf;
27use std::process::Command;
28use std::process::Stdio;
29use vmm_test_images::KnownTestArtifacts;
30
31#[derive(clap::Args)]
33pub struct VmmTestsRunCli {
34 #[clap(long)]
38 target: Option<VmmTestTargetCli>,
39
40 #[clap(long)]
46 dir: Option<PathBuf>,
47
48 #[clap(long, default_value = "all()")]
55 filter: String,
56
57 #[clap(long)]
59 verbose: bool,
60 #[clap(long)]
62 install_missing_deps: bool,
63
64 #[clap(long)]
66 release: bool,
67
68 #[clap(long)]
70 build_only: bool,
71 #[clap(long)]
73 copy_extras: bool,
74
75 #[clap(long)]
77 skip_vhd_prompt: bool,
78
79 #[clap(long)]
85 no_lazy_fetch: bool,
86
87 #[clap(long)]
89 custom_kernel_modules: Option<PathBuf>,
90 #[clap(long)]
92 custom_kernel: Option<PathBuf>,
93 #[clap(long)]
96 custom_uefi_firmware: Option<PathBuf>,
97
98 #[clap(long)]
100 ci_profile: bool,
101
102 #[clap(long)]
105 no_reuse_prepped_vhds: bool,
106
107 #[clap(long)]
111 pub disable_secure_avic: bool,
112}
113
114struct CargoNextestListRequest<'a> {
115 repo_root: &'a Path,
116 target: &'a str,
117 filter: &'a str,
118 release: bool,
119 include_ignored: bool,
120}
121
122struct RustSuite {
123 binary_path: PathBuf,
124 testcases: Vec<String>,
125}
126
127#[derive(Default, Debug)]
129struct ResolvedArtifactSelections {
130 build: BuildSelections,
132 downloads: BTreeSet<KnownTestArtifacts>,
134 needs_release_igvm: bool,
136 needs_hyperv: bool,
138 needs_hardware_isolation: bool,
140}
141
142impl IntoPipeline for VmmTestsRunCli {
143 fn into_pipeline(self, backend_hint: PipelineBackendHint) -> anyhow::Result<Pipeline> {
144 if !matches!(backend_hint, PipelineBackendHint::Local) {
145 anyhow::bail!("vmm-tests-run is for local use only")
146 }
147
148 let Self {
149 target,
150 dir,
151 filter,
152 verbose,
153 install_missing_deps,
154 release,
155 build_only,
156 copy_extras,
157 skip_vhd_prompt,
158 no_lazy_fetch,
159 custom_kernel_modules,
160 custom_kernel,
161 custom_uefi_firmware,
162 ci_profile,
163 no_reuse_prepped_vhds,
164 disable_secure_avic,
165 } = self;
166
167 let target = resolve_target(target, backend_hint)?;
168 let target_os = target.as_triple().operating_system;
169 let target_architecture = target.common_arch()?;
170 let target_str = target.as_triple().to_string();
171
172 let repo_root = crate::repo_root();
173
174 validate_output_dir(dir.as_deref(), target_os)?;
176 let test_content_dir = dir.unwrap_or_else(|| repo_root.join("target").join("vmm_tests"));
177 std::fs::create_dir_all(&test_content_dir).context("failed to create output directory")?;
178
179 log::info!(
182 "Discovering artifacts for filter: {} (target: {})",
183 filter,
184 target
185 );
186
187 let suites = run_cargo_nextest_list(CargoNextestListRequest {
189 repo_root: &repo_root,
190 target: &target_str,
191 filter: &filter,
192 release,
193 include_ignored: build_only,
197 })?;
198
199 if suites.is_empty() {
200 anyhow::bail!("No tests found for the given filter");
201 }
202
203 let mut artifacts = Vec::new();
205 for suite in suites.values() {
206 artifacts.append(&mut query_test_binary_artifacts(suite)?);
207 }
208
209 let mut resolved = ResolvedArtifactSelections::default();
211 for artifact in artifacts {
212 resolved.resolve_artifact(&artifact)?;
213 }
214
215 resolved.needs_hyperv = suites
217 .values()
218 .any(|s| s.testcases.iter().any(|name| name.contains("hyperv")));
219 resolved.needs_hardware_isolation = suites.values().any(|s| {
220 s.testcases
221 .iter()
222 .any(|name| name.contains("snp") || name.contains("tdx"))
223 });
224
225 if no_lazy_fetch {
239 log::info!("Lazy fetch disabled");
240 } else {
241 let mut hyperv_tests: usize = 0;
242 let mut hyperv_artifacts = Vec::new();
243 for (_, suite) in suites.iter() {
244 let hyperv_testcases: Vec<_> = suite
245 .testcases
246 .iter()
247 .filter(|name| name.contains("hyperv"))
248 .cloned()
249 .collect();
250
251 if !hyperv_testcases.is_empty() {
252 hyperv_tests += hyperv_testcases.len();
253 hyperv_artifacts.append(&mut query_test_binary_artifacts(&RustSuite {
254 binary_path: suite.binary_path.clone(),
255 testcases: hyperv_testcases,
256 })?);
257 }
258 }
259
260 resolved.downloads.retain(|a| !a.supports_blob_disk());
261
262 if hyperv_tests == 0 {
263 log::info!("Lazy fetch enabled: disk images will be streamed on demand via HTTP");
264 } else {
265 log::info!(
266 "Downloading disk images required by {} Hyper-V tests",
267 hyperv_tests
268 );
269 }
270
271 for artifact in hyperv_artifacts {
274 resolved.resolve_artifact(&artifact)?;
275 }
276 }
277
278 log::info!("Resolved selections: {:?}", resolved);
279
280 let openvmm_repo = flowey_lib_common::git_checkout::RepoSource::ExistingClone(
281 ReadVar::from_static(repo_root),
282 );
283
284 let mut pipeline = Pipeline::new();
285
286 let mut job = pipeline.new_job(
287 FlowPlatform::host(backend_hint),
288 FlowArch::host(backend_hint),
289 "build all dependencies and run vmm tests",
290 );
291
292 job = job.dep_on(|_| flowey_lib_hvlite::_jobs::cfg_versions::Request::Init);
293
294 if let (Some(kernel_path), Some(modules_path)) =
296 (custom_kernel.clone(), custom_kernel_modules.clone())
297 {
298 job =
299 job.dep_on(
300 move |_| flowey_lib_hvlite::_jobs::cfg_versions::Request::LocalKernel {
301 arch: target_architecture,
302 kernel: ReadVar::from_static(kernel_path),
303 modules: ReadVar::from_static(modules_path),
304 },
305 );
306 }
307
308 if let Some(fw_path) = custom_uefi_firmware {
310 job = job.dep_on(move |_| {
311 flowey_lib_hvlite::_jobs::cfg_versions::Request::LocalUefi(
312 target_architecture,
313 ReadVar::from_static(fw_path),
314 )
315 });
316 }
317
318 job = job
319 .dep_on(
320 |_| flowey_lib_hvlite::_jobs::cfg_hvlite_reposource::Params {
321 hvlite_repo_source: openvmm_repo.clone(),
322 },
323 )
324 .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_common::Params {
325 local_only: Some(flowey_lib_hvlite::_jobs::cfg_common::LocalOnlyParams {
326 interactive: true,
327 auto_install: install_missing_deps,
328 ignore_rust_version: true,
329 }),
330 verbose: ReadVar::from_static(verbose),
331 locked: false,
332 deny_warnings: false,
333 no_incremental: false,
334 })
335 .dep_on(|ctx| {
336 flowey_lib_hvlite::_jobs::local_build_and_run_nextest_vmm_tests::Params {
337 target,
338 test_content_dir,
339 selections: selections_from_resolved(filter, resolved, target_os),
340 release,
341 build_only,
342 copy_extras,
343 custom_kernel_modules,
344 custom_kernel,
345 skip_vhd_prompt,
346 nextest_profile: if ci_profile {
347 flowey_lib_hvlite::run_cargo_nextest_run::NextestProfile::Ci
348 } else {
349 flowey_lib_hvlite::run_cargo_nextest_run::NextestProfile::Default
350 },
351 reuse_prepped_vhds: !no_reuse_prepped_vhds,
352 disable_secure_avic,
353 done: ctx.new_done_handle(),
354 }
355 });
356
357 job.finish();
358
359 Ok(pipeline)
360 }
361}
362
363fn run_cargo_nextest_list<'a>(
367 req: CargoNextestListRequest<'a>,
368) -> anyhow::Result<BTreeMap<String, RustSuite>> {
369 let CargoNextestListRequest {
370 repo_root,
371 target,
372 filter,
373 release,
374 include_ignored,
375 } = req;
376
377 let nextest_check = Command::new("cargo")
379 .args(["nextest", "--version"])
380 .stdout(Stdio::null())
381 .stderr(Stdio::null())
382 .status();
383 match nextest_check {
384 Ok(status) if status.success() => {}
385 _ => anyhow::bail!(
386 "cargo-nextest not found. Run 'cargo install --locked cargo-nextest' first."
387 ),
388 }
389
390 let mut cmd = Command::new("cargo");
393 cmd.stderr(Stdio::inherit());
394 cmd.current_dir(repo_root).args([
395 "nextest",
396 "list",
397 "-p",
398 "vmm_tests",
399 "--target",
400 target,
401 "--filter-expr",
402 filter,
403 "--message-format",
404 "json",
405 ]);
406 if release {
407 cmd.arg("--release");
408 }
409 if include_ignored {
410 cmd.args(["--run-ignored", "all"]);
411 }
412 let nextest_output = cmd.output().context("failed to run cargo nextest list")?;
413 anyhow::ensure!(nextest_output.status.success(), "cargo nextest list failed",);
414 let nextest_stdout = String::from_utf8(nextest_output.stdout)
415 .map_err(|e| anyhow::anyhow!("nextest output is not valid UTF-8: {}", e))?;
416
417 parse_nextest_output(&nextest_stdout)
418}
419
420fn parse_nextest_output(stdout: &str) -> anyhow::Result<BTreeMap<String, RustSuite>> {
423 let json: serde_json::Value = serde_json::from_str(stdout)
424 .map_err(|e| anyhow::anyhow!("failed to parse nextest JSON output: {}", e))?;
425
426 let mut suites = BTreeMap::new();
427
428 for (name, suite) in json
429 .get("rust-suites")
430 .and_then(|s| s.as_object())
431 .context("no rust-suites object")?
432 {
433 let binary_path = PathBuf::from(
434 suite
435 .get("binary-path")
436 .and_then(|v| v.as_str())
437 .context("no binary-path str")?,
438 );
439
440 let testcases: Vec<_> = suite
441 .get("testcases")
442 .and_then(|t| t.as_object())
443 .context("no testcases object")?
444 .iter()
445 .filter(|(_, test_info)| {
446 test_info
447 .get("filter-match")
448 .and_then(|fm| fm.get("status"))
449 .and_then(|s| s.as_str())
450 .is_some_and(|s| s == "matches")
451 })
452 .map(|(test_name, _)| test_name.to_owned())
453 .collect();
454
455 if !testcases.is_empty() {
456 suites.insert(
457 name.to_owned(),
458 RustSuite {
459 binary_path,
460 testcases,
461 },
462 );
463 }
464 }
465
466 Ok(suites)
467}
468
469fn query_test_binary_artifacts(suite: &RustSuite) -> anyhow::Result<Vec<String>> {
473 log::info!("Using test binary: {}", suite.binary_path.display());
474 log::info!("Querying artifacts for {} tests", suite.testcases.len());
475 let stdin_data = suite
476 .testcases
477 .iter()
478 .map(|n| format!("{n}\n"))
479 .collect::<String>();
480 let mut child = Command::new(&suite.binary_path)
481 .args(["--list-required-artifacts", "--tests-from-stdin"])
482 .stdin(Stdio::piped())
483 .stdout(Stdio::piped())
484 .stderr(Stdio::piped())
485 .spawn()
486 .context("failed to spawn test binary")?;
487
488 child
489 .stdin
490 .take()
491 .expect("stdin was piped")
492 .write_all(stdin_data.as_bytes())
493 .context("failed to write test names to stdin")?;
494
495 let artifact_output = child
496 .wait_with_output()
497 .context("failed to wait for test binary")?;
498 anyhow::ensure!(
499 artifact_output.status.success(),
500 "test binary failed: {}",
501 String::from_utf8_lossy(&artifact_output.stderr)
502 );
503 let artifact_stdout = String::from_utf8(artifact_output.stdout)
504 .map_err(|e| anyhow::anyhow!("test output is not valid UTF-8: {}", e))?;
505
506 let ArtifactListOutput {
507 mut required,
508 mut optional,
509 } = serde_json::from_str(&artifact_stdout)
510 .map_err(|e| anyhow::anyhow!("failed to parse test output JSON: {}", e))?;
511
512 let mut artifacts = Vec::new();
513 artifacts.append(&mut required);
514 artifacts.append(&mut optional);
515 Ok(artifacts)
516}
517
518#[derive(clap::ValueEnum, Copy, Clone)]
519enum VmmTestTargetCli {
520 WindowsAarch64,
522 WindowsX64,
524 LinuxX64,
526}
527
528fn resolve_target(
530 target: Option<VmmTestTargetCli>,
531 backend_hint: PipelineBackendHint,
532) -> anyhow::Result<CommonTriple> {
533 let target = if let Some(t) = target {
534 t
535 } else {
536 match (
537 FlowArch::host(backend_hint),
538 FlowPlatform::host(backend_hint),
539 ) {
540 (FlowArch::Aarch64, FlowPlatform::Windows) => VmmTestTargetCli::WindowsAarch64,
541 (FlowArch::X86_64, FlowPlatform::Windows) => VmmTestTargetCli::WindowsX64,
542 (FlowArch::X86_64, FlowPlatform::Linux(_)) => VmmTestTargetCli::LinuxX64,
543 _ => anyhow::bail!("unsupported host"),
544 }
545 };
546
547 Ok(match target {
548 VmmTestTargetCli::WindowsAarch64 => CommonTriple::AARCH64_WINDOWS_MSVC,
549 VmmTestTargetCli::WindowsX64 => CommonTriple::X86_64_WINDOWS_MSVC,
550 VmmTestTargetCli::LinuxX64 => CommonTriple::X86_64_LINUX_GNU,
551 })
552}
553
554fn validate_output_dir(
561 dir: Option<&Path>,
562 target_os: target_lexicon::OperatingSystem,
563) -> anyhow::Result<()> {
564 if flowey_cli::running_in_wsl() && matches!(target_os, target_lexicon::OperatingSystem::Windows)
565 {
566 if let Some(dir) = dir {
567 if !flowey_cli::is_wsl_windows_path(dir) {
568 anyhow::bail!(
569 "When targeting Windows from WSL, --dir must be a path on Windows \
570 (i.e., on a DrvFs mount like /mnt/c/vmm_tests). \
571 Got: {}",
572 dir.display()
573 );
574 }
575 } else {
576 anyhow::bail!(
577 "An output directory on the Windows filesystem \
578 must be specified when targeting Windows from WSL."
579 )
580 }
581 }
582 Ok(())
583}
584
585fn selections_from_resolved(
587 filter: String,
588 resolved: ResolvedArtifactSelections,
589 target_os: target_lexicon::OperatingSystem,
590) -> VmmTestSelections {
591 VmmTestSelections {
592 filter,
593 artifacts: resolved.downloads.into_iter().collect(),
594 build: resolved.build.clone(),
595 deps: match target_os {
596 target_lexicon::OperatingSystem::Windows => {
597 VmmTestsDepSelections::Windows(VmmTestsDepSelectionsWindows {
598 hyperv: resolved.needs_hyperv,
599 whp: resolved.build.openvmm,
600 hardware_isolation: resolved.needs_hardware_isolation,
601 })
602 }
603 target_lexicon::OperatingSystem::Linux => VmmTestsDepSelections::Linux,
604 _ => unreachable!(),
605 },
606 needs_release_igvm: resolved.needs_release_igvm,
607 }
608}
609
610impl ResolvedArtifactSelections {
611 fn resolve_artifact(&mut self, id: &str) -> anyhow::Result<()> {
613 match id {
614 petri_artifacts_vmm_test::artifacts::OPENVMM_WIN_X64::GLOBAL_UNIQUE_ID
616 | petri_artifacts_vmm_test::artifacts::OPENVMM_LINUX_X64::GLOBAL_UNIQUE_ID
617 | petri_artifacts_vmm_test::artifacts::OPENVMM_WIN_AARCH64::GLOBAL_UNIQUE_ID
618 | petri_artifacts_vmm_test::artifacts::OPENVMM_LINUX_AARCH64::GLOBAL_UNIQUE_ID
619 | petri_artifacts_vmm_test::artifacts::OPENVMM_MACOS_AARCH64::GLOBAL_UNIQUE_ID => {
620 self.build.openvmm = true;
621 }
622
623 petri_artifacts_vmm_test::artifacts::OPENVMM_VHOST_LINUX_X64::GLOBAL_UNIQUE_ID
625 | petri_artifacts_vmm_test::artifacts::OPENVMM_VHOST_LINUX_AARCH64 ::GLOBAL_UNIQUE_ID => {
626 self.build.openvmm_vhost = true;
627 }
628
629 petri_artifacts_vmm_test::artifacts::openhcl_igvm::LATEST_STANDARD_X64::GLOBAL_UNIQUE_ID
631 | petri_artifacts_vmm_test::artifacts::openhcl_igvm::LATEST_STANDARD_AARCH64::GLOBAL_UNIQUE_ID =>
632 {
633 self.build.openhcl_standard = true;
634 }
635 petri_artifacts_vmm_test::artifacts::openhcl_igvm::LATEST_STANDARD_DEV_KERNEL_X64::GLOBAL_UNIQUE_ID
636 | petri_artifacts_vmm_test::artifacts::openhcl_igvm::LATEST_STANDARD_DEV_KERNEL_AARCH64::GLOBAL_UNIQUE_ID => {
637 self.build.openhcl_standard_dev = true;
638 }
639 petri_artifacts_vmm_test::artifacts::openhcl_igvm::LATEST_CVM_X64::GLOBAL_UNIQUE_ID
640 =>
641 {
642 self.build.openhcl_cvm = true;
643 }
644 petri_artifacts_vmm_test::artifacts::openhcl_igvm::LATEST_LINUX_DIRECT_TEST_X64::GLOBAL_UNIQUE_ID =>
645 {
646 self.build.openhcl_linux_direct = true;
647 }
648
649 petri_artifacts_vmm_test::artifacts::openhcl_igvm::LATEST_RELEASE_STANDARD_X64::GLOBAL_UNIQUE_ID
651 | petri_artifacts_vmm_test::artifacts::openhcl_igvm::LATEST_RELEASE_LINUX_DIRECT_X64::GLOBAL_UNIQUE_ID
652 | petri_artifacts_vmm_test::artifacts::openhcl_igvm::LATEST_RELEASE_STANDARD_AARCH64::GLOBAL_UNIQUE_ID =>
653 {
654 self.needs_release_igvm = true;
656 }
657
658 petri_artifacts_vmm_test::artifacts::test_vhd::GUEST_TEST_UEFI_X64::GLOBAL_UNIQUE_ID
660 | petri_artifacts_vmm_test::artifacts::test_vhd::GUEST_TEST_UEFI_AARCH64 ::GLOBAL_UNIQUE_ID => {
661 self.build.guest_test_uefi = true;
662 }
663
664 petri_artifacts_vmm_test::artifacts::tmks::SIMPLE_TMK_X64::GLOBAL_UNIQUE_ID
666 | petri_artifacts_vmm_test::artifacts::tmks::SIMPLE_TMK_AARCH64 ::GLOBAL_UNIQUE_ID => {
667 self.build.tmks = true;
668 }
669
670 petri_artifacts_vmm_test::artifacts::tmks::TMK_VMM_WIN_X64::GLOBAL_UNIQUE_ID
672 | petri_artifacts_vmm_test::artifacts::tmks::TMK_VMM_WIN_AARCH64::GLOBAL_UNIQUE_ID => {
673 self.build.tmk_vmm_windows = true;
674 }
675 petri_artifacts_vmm_test::artifacts::tmks::TMK_VMM_LINUX_X64::GLOBAL_UNIQUE_ID
676 | petri_artifacts_vmm_test::artifacts::tmks::TMK_VMM_LINUX_AARCH64::GLOBAL_UNIQUE_ID
677 | petri_artifacts_vmm_test::artifacts::tmks::TMK_VMM_LINUX_X64_MUSL::GLOBAL_UNIQUE_ID
678 | petri_artifacts_vmm_test::artifacts::tmks::TMK_VMM_LINUX_AARCH64_MUSL::GLOBAL_UNIQUE_ID
679 | petri_artifacts_vmm_test::artifacts::tmks::TMK_VMM_MACOS_AARCH64::GLOBAL_UNIQUE_ID => {
680 self.build.tmk_vmm_linux = true;
681 }
682
683 petri_artifacts_vmm_test::artifacts::VMGSTOOL_WIN_X64::GLOBAL_UNIQUE_ID
685 | petri_artifacts_vmm_test::artifacts::VMGSTOOL_WIN_AARCH64::GLOBAL_UNIQUE_ID => {
686 self.build.vmgstool = true;
687 }
688 petri_artifacts_vmm_test::artifacts::VMGSTOOL_LINUX_X64::GLOBAL_UNIQUE_ID
689 | petri_artifacts_vmm_test::artifacts::VMGSTOOL_LINUX_AARCH64::GLOBAL_UNIQUE_ID
690 | petri_artifacts_vmm_test::artifacts::VMGSTOOL_MACOS_AARCH64::GLOBAL_UNIQUE_ID => {
691 self.build.vmgstool = true;
692 }
693
694 petri_artifacts_vmm_test::artifacts::guest_tools::TPM_GUEST_TESTS_WINDOWS_X64::GLOBAL_UNIQUE_ID => {
696 self.build.tpm_guest_tests_windows = true;
697 }
698 petri_artifacts_vmm_test::artifacts::guest_tools::TPM_GUEST_TESTS_LINUX_X64::GLOBAL_UNIQUE_ID => {
699 self.build.tpm_guest_tests_linux = true;
700 }
701
702 petri_artifacts_vmm_test::artifacts::host_tools::TEST_IGVM_AGENT_RPC_SERVER_WINDOWS_X64::GLOBAL_UNIQUE_ID =>
704 {
705 self.build.test_igvm_agent_rpc_server = true;
706 }
707
708 petri_artifacts_vmm_test::artifacts::loadable::LINUX_DIRECT_TEST_KERNEL_X64::GLOBAL_UNIQUE_ID
710 | petri_artifacts_vmm_test::artifacts::loadable::LINUX_DIRECT_TEST_INITRD_X64::GLOBAL_UNIQUE_ID
711 | petri_artifacts_vmm_test::artifacts::loadable::LINUX_DIRECT_TEST_BZIMAGE_X64::GLOBAL_UNIQUE_ID
712 | petri_artifacts_vmm_test::artifacts::loadable::LINUX_DIRECT_TEST_KERNEL_AARCH64::GLOBAL_UNIQUE_ID
713 | petri_artifacts_vmm_test::artifacts::loadable::LINUX_DIRECT_TEST_INITRD_AARCH64::GLOBAL_UNIQUE_ID
714 | petri_artifacts_vmm_test::artifacts::loadable::PCAT_FIRMWARE_X64::GLOBAL_UNIQUE_ID
715 | petri_artifacts_vmm_test::artifacts::loadable::SVGA_FIRMWARE_X64::GLOBAL_UNIQUE_ID
716 | petri_artifacts_vmm_test::artifacts::loadable::UEFI_FIRMWARE_X64::GLOBAL_UNIQUE_ID
717 | petri_artifacts_vmm_test::artifacts::loadable::UEFI_FIRMWARE_AARCH64::GLOBAL_UNIQUE_ID => {
718 }
720
721 petri_artifacts_vmm_test::artifacts::test_vhd::GEN1_WINDOWS_DATA_CENTER_CORE2022_X64::GLOBAL_UNIQUE_ID =>
723 {
724 self.downloads
725 .insert(KnownTestArtifacts::Gen1WindowsDataCenterCore2022X64Vhd);
726 }
727 petri_artifacts_vmm_test::artifacts::test_vhd::GEN2_WINDOWS_DATA_CENTER_CORE2022_X64::GLOBAL_UNIQUE_ID =>
728 {
729 self.downloads
730 .insert(KnownTestArtifacts::Gen2WindowsDataCenterCore2022X64Vhd);
731 }
732 petri_artifacts_vmm_test::artifacts::test_vhd::GEN2_WINDOWS_DATA_CENTER_CORE2025_X64::GLOBAL_UNIQUE_ID =>
733 {
734 self.downloads
735 .insert(KnownTestArtifacts::Gen2WindowsDataCenterCore2025X64Vhd);
736 }
737 petri_artifacts_vmm_test::artifacts::test_vhd::GEN2_WINDOWS_DATA_CENTER_CORE2025_X64_PREPPED::GLOBAL_UNIQUE_ID =>
738 {
739 self.build.prep_steps = true;
740 }
741 petri_artifacts_vmm_test::artifacts::test_vhd::FREE_BSD_13_2_X64::GLOBAL_UNIQUE_ID => {
742 self.downloads.insert(KnownTestArtifacts::FreeBsd13_2X64Vhd);
743 }
744 petri_artifacts_vmm_test::artifacts::test_vhd::ALPINE_3_23_X64::GLOBAL_UNIQUE_ID => {
745 self.downloads.insert(KnownTestArtifacts::Alpine323X64Vhd);
746 }
747 petri_artifacts_vmm_test::artifacts::test_vhd::ALPINE_3_23_AARCH64::GLOBAL_UNIQUE_ID => {
748 self.downloads
749 .insert(KnownTestArtifacts::Alpine323Aarch64Vhd);
750 }
751 petri_artifacts_vmm_test::artifacts::test_vhd::UBUNTU_2404_SERVER_X64::GLOBAL_UNIQUE_ID => {
752 self.downloads
753 .insert(KnownTestArtifacts::Ubuntu2404ServerX64Vhd);
754 }
755 petri_artifacts_vmm_test::artifacts::test_vhd::UBUNTU_2504_SERVER_X64::GLOBAL_UNIQUE_ID => {
756 self.downloads
757 .insert(KnownTestArtifacts::Ubuntu2504ServerX64Vhd);
758 }
759 petri_artifacts_vmm_test::artifacts::test_vhd::UBUNTU_2404_SERVER_AARCH64::GLOBAL_UNIQUE_ID => {
760 self.downloads
761 .insert(KnownTestArtifacts::Ubuntu2404ServerAarch64Vhd);
762 }
763 petri_artifacts_vmm_test::artifacts::test_vhd::WINDOWS_11_ENTERPRISE_AARCH64::GLOBAL_UNIQUE_ID => {
764 self.downloads
765 .insert(KnownTestArtifacts::Windows11EnterpriseAarch64Vhdx);
766 }
767
768 petri_artifacts_vmm_test::artifacts::test_iso::FREE_BSD_13_2_X64::GLOBAL_UNIQUE_ID => {
770 self.downloads.insert(KnownTestArtifacts::FreeBsd13_2X64Iso);
771 }
772
773 petri_artifacts_vmm_test::artifacts::test_vmgs::VMGS_WITH_BOOT_ENTRY::GLOBAL_UNIQUE_ID => {
775 self.downloads.insert(KnownTestArtifacts::VmgsWithBootEntry);
776 }
777 petri_artifacts_vmm_test::artifacts::test_vmgs::VMGS_WITH_16K_TPM::GLOBAL_UNIQUE_ID => {
778 self.downloads.insert(KnownTestArtifacts::VmgsWith16kTpm);
779 }
780
781 petri_artifacts_vmm_test::artifacts::openhcl_igvm::um_bin::LATEST_LINUX_DIRECT_TEST_X64::GLOBAL_UNIQUE_ID
783 | petri_artifacts_vmm_test::artifacts::openhcl_igvm::um_dbg::LATEST_LINUX_DIRECT_TEST_X64::GLOBAL_UNIQUE_ID =>
784 {
785 self.build.openhcl_linux_direct = true;
786 }
787
788 petri_artifacts_common::artifacts::TEST_LOG_DIRECTORY::GLOBAL_UNIQUE_ID => {}
790
791 petri_artifacts_vmm_test::artifacts::virtio_win::VIRTIO_WIN_DRIVERS::GLOBAL_UNIQUE_ID => {}
793
794 petri_artifacts_common::artifacts::PIPETTE_LINUX_X64::GLOBAL_UNIQUE_ID
796 | petri_artifacts_common::artifacts::PIPETTE_LINUX_AARCH64::GLOBAL_UNIQUE_ID => {
797 self.build.pipette_linux = true;
798 }
799 petri_artifacts_common::artifacts::PIPETTE_WINDOWS_X64::GLOBAL_UNIQUE_ID
800 | petri_artifacts_common::artifacts::PIPETTE_WINDOWS_AARCH64::GLOBAL_UNIQUE_ID => {
801 self.build.pipette_windows = true;
802 }
803
804 _ => anyhow::bail!("unknown artifact: {id}"),
805 };
806 Ok(())
807 }
808}