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