flowey_lib_hvlite/
run_cargo_nextest_run.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Run cargo-nextest tests in the context of the HvLite repo.
5//!
6//! Uses the generic [`flowey_lib_common::run_cargo_nextest_run::Node`]
7//! under-the-hood.
8
9use flowey::node::prelude::*;
10use flowey_lib_common::run_cargo_nextest_run::NextestRunKind;
11use flowey_lib_common::run_cargo_nextest_run::TestResults;
12use std::collections::BTreeMap;
13
14/// Nextest profiles defined in HvLite's `.config/nextest.toml`
15#[derive(Serialize, Deserialize)]
16pub enum NextestProfile {
17    Default,
18    Ci,
19}
20
21impl NextestProfile {
22    pub fn as_str(&self) -> &'static str {
23        match self {
24            NextestProfile::Default => "default",
25            NextestProfile::Ci => "ci",
26        }
27    }
28}
29
30flowey_request! {
31    pub struct Request {
32        /// Friendly name for this test group that will be displayed in logs.
33        pub friendly_name: String,
34        /// What kind of test run this is (inline build vs. from nextest archive).
35        pub run_kind: NextestRunKind,
36        /// Nextest profile to use when running the source code
37        pub nextest_profile: NextestProfile,
38        /// Nextest test filter expression
39        pub nextest_filter_expr: Option<String>,
40        /// Nextest working directory (defaults to repo root)
41        pub nextest_working_dir: Option<ReadVar<PathBuf>>,
42        /// Nextest configuration file (defaults to config in repo)
43        pub nextest_config_file: Option<ReadVar<PathBuf>>,
44        /// Whether to run ignored test
45        pub run_ignored: bool,
46        /// Additional env vars set when executing the tests.
47        pub extra_env: Option<ReadVar<BTreeMap<String, String>>>,
48        /// Wait for specified side-effects to resolve before building / running any
49        /// tests. (e.g: to allow for some ambient packages / dependencies to
50        /// get installed).
51        pub pre_run_deps: Vec<ReadVar<SideEffect>>,
52        /// Results of running the tests
53        pub results: WriteVar<TestResults>,
54    }
55}
56
57new_flow_node!(struct Node);
58
59impl FlowNode for Node {
60    type Request = Request;
61
62    fn imports(ctx: &mut ImportCtx<'_>) {
63        ctx.import::<crate::git_checkout_openvmm_repo::Node>();
64        ctx.import::<flowey_lib_common::run_cargo_nextest_run::Node>();
65    }
66
67    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
68        let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
69
70        let default_nextest_config_file =
71            openvmm_repo_path.map(ctx, |p| p.join(".config").join("nextest.toml"));
72
73        let base_env = [
74            // Used by the test_with_tracing macro in test runners
75            ("RUST_LOG", "trace"),
76        ]
77        .into_iter()
78        .map(|(a, b)| (a.to_owned(), b.to_owned()))
79        .collect::<BTreeMap<_, _>>();
80
81        for Request {
82            friendly_name,
83            run_kind,
84            nextest_profile,
85            nextest_filter_expr,
86            nextest_working_dir,
87            nextest_config_file,
88            run_ignored,
89            mut pre_run_deps,
90            results,
91            extra_env,
92        } in requests
93        {
94            let extra_env = if let Some(with_env) = extra_env {
95                let base_env = base_env.clone();
96                with_env.map(ctx, move |mut m| {
97                    m.extend(base_env);
98                    m
99                })
100            } else {
101                ReadVar::from_static(base_env.clone())
102            };
103
104            let working_dir = if let Some(nextest_working_dir) = nextest_working_dir {
105                pre_run_deps.push(openvmm_repo_path.clone().into_side_effect());
106                nextest_working_dir
107            } else {
108                openvmm_repo_path.clone()
109            };
110
111            let config_file = if let Some(nextest_config_file) = nextest_config_file {
112                pre_run_deps.push(default_nextest_config_file.clone().into_side_effect());
113                nextest_config_file
114            } else {
115                default_nextest_config_file.clone()
116            };
117
118            ctx.req(flowey_lib_common::run_cargo_nextest_run::Request::Run(
119                flowey_lib_common::run_cargo_nextest_run::Run {
120                    friendly_name,
121                    run_kind,
122                    working_dir,
123                    config_file,
124                    tool_config_files: Vec::new(),
125                    nextest_profile: nextest_profile.as_str().to_owned(),
126                    extra_env: Some(extra_env),
127                    with_rlimit_unlimited_core_size: true,
128                    nextest_filter_expr,
129                    run_ignored,
130                    pre_run_deps,
131                    results,
132                },
133            ));
134        }
135
136        Ok(())
137    }
138}