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,mesh_node=info"),
76            // Used by the process spawned for VMM tests
77            ("OPENVMM_LOG", "debug,mesh_node=info"),
78        ]
79        .into_iter()
80        .map(|(a, b)| (a.to_owned(), b.to_owned()))
81        .collect::<BTreeMap<_, _>>();
82
83        for Request {
84            friendly_name,
85            run_kind,
86            nextest_profile,
87            nextest_filter_expr,
88            nextest_working_dir,
89            nextest_config_file,
90            run_ignored,
91            mut pre_run_deps,
92            results,
93            extra_env,
94        } in requests
95        {
96            let extra_env = if let Some(with_env) = extra_env {
97                let base_env = base_env.clone();
98                with_env.map(ctx, move |mut m| {
99                    m.extend(base_env);
100                    m
101                })
102            } else {
103                ReadVar::from_static(base_env.clone())
104            };
105
106            let working_dir = if let Some(nextest_working_dir) = nextest_working_dir {
107                pre_run_deps.push(openvmm_repo_path.clone().into_side_effect());
108                nextest_working_dir
109            } else {
110                openvmm_repo_path.clone()
111            };
112
113            let config_file = if let Some(nextest_config_file) = nextest_config_file {
114                pre_run_deps.push(default_nextest_config_file.clone().into_side_effect());
115                nextest_config_file
116            } else {
117                default_nextest_config_file.clone()
118            };
119
120            ctx.req(flowey_lib_common::run_cargo_nextest_run::Request::Run(
121                flowey_lib_common::run_cargo_nextest_run::Run {
122                    friendly_name,
123                    run_kind,
124                    working_dir,
125                    config_file,
126                    tool_config_files: Vec::new(),
127                    nextest_profile: nextest_profile.as_str().to_owned(),
128                    extra_env: Some(extra_env),
129                    with_rlimit_unlimited_core_size: true,
130                    nextest_filter_expr,
131                    run_ignored,
132                    pre_run_deps,
133                    results,
134                },
135            ));
136        }
137
138        Ok(())
139    }
140}