flowey_lib_hvlite/
build_nextest_unit_tests.rs1use crate::init_openvmm_magicpath_openhcl_sysroot::OpenvmmSysrootArch;
11use crate::run_cargo_build::common::CommonArch;
12use crate::run_cargo_build::common::CommonPlatform;
13use crate::run_cargo_build::common::CommonProfile;
14use crate::run_cargo_build::common::CommonTriple;
15use crate::run_cargo_nextest_run::NextestProfile;
16use flowey::node::prelude::*;
17use flowey_lib_common::run_cargo_build::CargoBuildProfile;
18use flowey_lib_common::run_cargo_build::CargoFeatureSet;
19use flowey_lib_common::run_cargo_nextest_run::TestResults;
20use flowey_lib_common::run_cargo_nextest_run::build_params::TestPackages;
21
22#[derive(Serialize, Deserialize)]
24pub struct NextestUnitTestArchive {
25 #[serde(rename = "unit_tests.tar.zst")]
26 pub archive_file: PathBuf,
27}
28
29#[derive(Serialize, Deserialize)]
31pub enum BuildNextestUnitTestMode {
32 ImmediatelyRun {
35 nextest_profile: NextestProfile,
36 results: WriteVar<TestResults>,
37 },
38 Archive(WriteVar<NextestUnitTestArchive>),
41}
42
43flowey_request! {
44 pub struct Request {
45 pub target: target_lexicon::Triple,
47 pub profile: CommonProfile,
49 pub build_mode: BuildNextestUnitTestMode,
51 }
52}
53
54new_flow_node!(struct Node);
55
56impl FlowNode for Node {
57 type Request = Request;
58
59 fn imports(ctx: &mut ImportCtx<'_>) {
60 ctx.import::<crate::build_xtask::Node>();
61 ctx.import::<crate::git_checkout_openvmm_repo::Node>();
62 ctx.import::<crate::init_openvmm_magicpath_openhcl_sysroot::Node>();
63 ctx.import::<crate::install_openvmm_rust_build_essential::Node>();
64 ctx.import::<crate::run_cargo_nextest_run::Node>();
65 ctx.import::<crate::init_cross_build::Node>();
66 ctx.import::<flowey_lib_common::run_cargo_nextest_archive::Node>();
67 }
68
69 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
70 let flowey_platform = ctx.platform();
71 let flowey_arch = ctx.arch();
72
73 let xtask_target = CommonTriple::Common {
74 arch: match flowey_arch {
75 FlowArch::X86_64 => CommonArch::X86_64,
76 FlowArch::Aarch64 => CommonArch::Aarch64,
77 arch => anyhow::bail!("unsupported arch {arch}"),
78 },
79 platform: match flowey_platform {
80 FlowPlatform::Windows => CommonPlatform::WindowsMsvc,
81 FlowPlatform::Linux(_) => CommonPlatform::LinuxGnu,
82 FlowPlatform::MacOs => CommonPlatform::MacOs,
83 platform => anyhow::bail!("unsupported platform {platform}"),
84 },
85 };
86 let xtask = ctx.reqv(|v| crate::build_xtask::Request {
87 target: xtask_target,
88 xtask: v,
89 });
90
91 let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
92
93 let ambient_deps = vec![ctx.reqv(crate::install_openvmm_rust_build_essential::Request)];
96
97 let test_packages = ctx.emit_rust_stepv("determine unit test exclusions", |ctx| {
98 let xtask = xtask.claim(ctx);
99 let openvmm_repo_path = openvmm_repo_path.clone().claim(ctx);
100 move |rt| {
101 let xtask = rt.read(xtask);
102 let openvmm_repo_path = rt.read(openvmm_repo_path);
103
104 let mut exclude = [
105 "whp",
108 "kvm",
109 "openvmm",
110 "vmm_tests",
112 "guest_test_uefi",
114 "inspect_derive",
121 "mesh_derive",
122 "save_restore_derive",
123 "test_with_tracing_macro",
124 "pal_async_test",
125 "vmm_test_macros",
126 ]
127 .map(|x| x.to_string())
128 .to_vec();
129
130 {
133 let xtask_bin = match xtask {
134 crate::build_xtask::XtaskOutput::LinuxBin { bin, dbg: _ } => bin,
135 crate::build_xtask::XtaskOutput::WindowsBin { exe, pdb: _ } => exe,
136 };
137
138 let sh = xshell::Shell::new()?;
139 sh.change_dir(openvmm_repo_path);
140 let output = xshell::cmd!(sh, "{xtask_bin} fuzz list --crates").output()?;
141 let output = String::from_utf8(output.stdout)?;
142
143 let fuzz_crates = output.trim().split('\n').map(|s| s.to_owned());
144 exclude.extend(fuzz_crates);
145 }
146
147 Ok(TestPackages::Workspace { exclude })
148 }
149 });
150
151 for Request {
152 target,
153 profile,
154 build_mode,
155 } in requests
156 {
157 let mut pre_run_deps = ambient_deps.clone();
158
159 let sysroot_arch = match target.architecture {
160 target_lexicon::Architecture::X86_64 => OpenvmmSysrootArch::X64,
161 target_lexicon::Architecture::Aarch64(_) => OpenvmmSysrootArch::Aarch64,
162 arch => anyhow::bail!("unsupported arch {arch}"),
163 };
164
165 if matches!(target.environment, target_lexicon::Environment::Musl) {
169 pre_run_deps.push(
170 ctx.reqv(|v| crate::init_openvmm_magicpath_openhcl_sysroot::Request {
171 arch: sysroot_arch,
172 path: v,
173 })
174 .into_side_effect(),
175 );
176 }
177
178 let features = if matches!(
188 target.operating_system,
189 target_lexicon::OperatingSystem::Windows
190 ) {
191 CargoFeatureSet::Specific(vec!["ci".into()])
192 } else {
193 CargoFeatureSet::All
194 };
195
196 let injected_env = ctx.reqv(|v| crate::init_cross_build::Request {
197 target: target.clone(),
198 injected_env: v,
199 });
200
201 let build_params =
202 flowey_lib_common::run_cargo_nextest_run::build_params::NextestBuildParams {
203 packages: test_packages.clone(),
204 features,
205 no_default_features: false,
206 target: target.clone(),
207 profile: match profile {
208 CommonProfile::Release => CargoBuildProfile::Release,
209 CommonProfile::Debug => CargoBuildProfile::Debug,
210 },
211 extra_env: injected_env,
212 };
213
214 match build_mode {
215 BuildNextestUnitTestMode::ImmediatelyRun {
216 nextest_profile,
217 results,
218 } => ctx.req(crate::run_cargo_nextest_run::Request {
219 friendly_name: "unit-tests".into(),
220 run_kind: flowey_lib_common::run_cargo_nextest_run::NextestRunKind::BuildAndRun(
221 build_params,
222 ),
223 nextest_profile,
224 nextest_filter_expr: None,
225 nextest_working_dir: None,
226 nextest_config_file: None,
227 run_ignored: false,
228 extra_env: None,
229 pre_run_deps,
230 results,
231 }),
232 BuildNextestUnitTestMode::Archive(unit_tests_archive) => {
233 let archive_file =
234 ctx.reqv(|v| flowey_lib_common::run_cargo_nextest_archive::Request {
235 friendly_label: "unit-tests".into(),
236 working_dir: openvmm_repo_path.clone(),
237 build_params,
238 pre_run_deps,
239 archive_file: v,
240 });
241
242 ctx.emit_minor_rust_step("report built unit tests", |ctx| {
243 let archive_file = archive_file.claim(ctx);
244 let unit_tests = unit_tests_archive.claim(ctx);
245 |rt| {
246 let archive_file = rt.read(archive_file);
247 rt.write(unit_tests, &NextestUnitTestArchive { archive_file });
248 }
249 });
250 }
251 }
252 }
253
254 Ok(())
255 }
256}