Skip to content

Commit 2b24896

Browse files
committed
chore: add executor tests
1 parent a85fe55 commit 2b24896

3 files changed

Lines changed: 189 additions & 41 deletions

File tree

Cargo.lock

Lines changed: 55 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ procfs = "0.17.0"
6262
temp-env = { version = "0.3.6", features = ["async_closure"] }
6363
insta = { version = "1.29.0", features = ["json", "redactions"] }
6464
test-with = { version = "0.15", default-features = false, features = [] }
65+
rstest = { version = "0.25.0", default-features = false }
6566

6667
[workspace.metadata.release]
6768
sign-tag = true

src/run/runner/tests.rs

Lines changed: 133 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,91 +5,183 @@ use crate::run::runner::interfaces::RunData;
55
use crate::run::runner::valgrind::executor::ValgrindExecutor;
66
use crate::run::{RunnerMode, runner::wall_time::executor::WallTimeExecutor};
77
use tempfile::TempDir;
8+
use tokio::sync::{OnceCell, Semaphore, SemaphorePermit};
89

10+
const SIMPLE_ECHO_SCRIPT: &str = "echo 'Hello, World!'";
911
const MULTILINE_ECHO_SCRIPT: &str = "echo \"Working\"
1012
echo \"with\"
1113
echo \"multiple lines\"";
12-
1314
const MULTILINE_ECHO_WITH_SEMICOLONS: &str = "echo \"Working\";
1415
echo \"with\";
1516
echo \"multiple lines\";";
16-
1717
const DIRECTORY_CHECK_SCRIPT: &str = "cd /tmp
1818
# Check that the directory is actually changed
1919
if [ $(basename $(pwd)) != \"tmp\" ]; then
2020
exit 1
2121
fi";
22+
const ENV_VAR_VALIDATION_SCRIPT: &str = "
23+
output=$(echo \"$MY_ENV_VAR\")
24+
if [ \"$output\" != \"Hello\" ]; then
25+
echo \"Assertion failed: Expected 'Hello' but got '$output'\"
26+
exit 1
27+
fi";
2228

23-
const BENCHMARK_COMMANDS: [&str; 5] = [
24-
"echo 'Hello, World!'",
25-
MULTILINE_ECHO_WITH_SEMICOLONS,
26-
MULTILINE_ECHO_WITH_SEMICOLONS,
29+
const TESTS: [&str; 5] = [
30+
SIMPLE_ECHO_SCRIPT,
2731
MULTILINE_ECHO_SCRIPT,
32+
MULTILINE_ECHO_WITH_SEMICOLONS,
2833
DIRECTORY_CHECK_SCRIPT,
34+
ENV_VAR_VALIDATION_SCRIPT,
2935
];
3036

3137
async fn create_test_setup() -> (SystemInfo, RunData, TempDir) {
32-
let temp_dir = TempDir::new().unwrap();
38+
let system_info = SystemInfo::new().unwrap();
3339

34-
let system_info = SystemInfo::test();
40+
let temp_dir = TempDir::new().unwrap();
3541
let run_data = RunData {
3642
profile_folder: temp_dir.path().to_path_buf(),
3743
};
38-
3944
(system_info, run_data, temp_dir)
4045
}
4146

42-
#[tokio::test]
43-
async fn test_valgrind_executor() {
44-
let (system_info, run_data, _temp_dir) = create_test_setup().await;
47+
mod valgrind {
48+
use super::*;
4549

46-
let executor = ValgrindExecutor;
47-
executor.setup(&system_info).await.unwrap();
50+
async fn get_valgrind_executor() -> &'static ValgrindExecutor {
51+
static VALGRIND_EXECUTOR: OnceCell<ValgrindExecutor> = OnceCell::const_new();
4852

49-
for cmd in BENCHMARK_COMMANDS {
50-
eprintln!("Running command: {cmd}");
53+
VALGRIND_EXECUTOR
54+
.get_or_init(|| async {
55+
let executor = ValgrindExecutor;
56+
let system_info = SystemInfo::new().unwrap();
57+
executor.setup(&system_info).await.unwrap();
58+
executor
59+
})
60+
.await
61+
}
5162

52-
let config = Config {
63+
fn valgrind_config(command: &str) -> Config {
64+
Config {
5365
mode: RunnerMode::Instrumentation,
54-
command: cmd.to_string(),
66+
command: command.to_string(),
5567
..Config::test()
56-
};
68+
}
69+
}
5770

71+
#[rstest::rstest]
72+
#[case(TESTS[0])]
73+
#[case(TESTS[1])]
74+
#[case(TESTS[2])]
75+
#[case(TESTS[3])]
76+
#[tokio::test]
77+
async fn test_valgrind_executor(#[case] cmd: &str) {
78+
let (system_info, run_data, _temp_dir) = create_test_setup().await;
79+
let executor = get_valgrind_executor().await;
80+
81+
let config = valgrind_config(cmd);
5882
executor
5983
.run(&config, &system_info, &run_data, &None)
6084
.await
6185
.unwrap();
62-
executor
63-
.teardown(&config, &system_info, &run_data)
64-
.await
65-
.unwrap();
6686
}
67-
}
6887

69-
#[tokio::test]
70-
async fn test_walltime_executor() {
71-
let (system_info, run_data, _temp_dir) = create_test_setup().await;
88+
#[rstest::rstest]
89+
#[case("MY_ENV_VAR", "Hello", ENV_VAR_VALIDATION_SCRIPT)]
90+
#[tokio::test]
91+
async fn test_valgrind_executor_with_env(
92+
#[case] env_var: &str,
93+
#[case] env_value: &str,
94+
#[case] cmd: &str,
95+
) {
96+
let (system_info, run_data, _temp_dir) = create_test_setup().await;
97+
let executor = get_valgrind_executor().await;
98+
99+
temp_env::async_with_vars(&[(env_var, Some(env_value))], async {
100+
let config = valgrind_config(cmd);
101+
executor
102+
.run(&config, &system_info, &run_data, &None)
103+
.await
104+
.unwrap();
105+
})
106+
.await;
107+
}
108+
}
72109

73-
let executor = WallTimeExecutor::new();
74-
executor.setup(&system_info).await.unwrap();
110+
mod walltime {
111+
use super::*;
112+
113+
async fn get_walltime_executor() -> (SemaphorePermit<'static>, WallTimeExecutor) {
114+
static WALLTIME_INIT: OnceCell<()> = OnceCell::const_new();
115+
static WALLTIME_SEMAPHORE: OnceCell<Semaphore> = OnceCell::const_new();
116+
117+
WALLTIME_INIT
118+
.get_or_init(|| async {
119+
let executor = WallTimeExecutor::new();
120+
let system_info = SystemInfo::new().unwrap();
121+
executor.setup(&system_info).await.unwrap();
122+
})
123+
.await;
124+
125+
// We can't execute multiple walltime executors in parallel because perf isn't thread-safe (yet). We have to
126+
// use a semaphore to limit concurrent access.
127+
let semaphore = WALLTIME_SEMAPHORE
128+
.get_or_init(|| async { Semaphore::new(1) })
129+
.await;
130+
let permit = semaphore.acquire().await.unwrap();
131+
132+
(permit, WallTimeExecutor::new())
133+
}
75134

76-
for enable_perf in [false, true] {
77-
for cmd in BENCHMARK_COMMANDS {
78-
eprintln!("Running command: {cmd}");
135+
fn walltime_config(command: &str, enable_perf: bool) -> Config {
136+
Config {
137+
mode: RunnerMode::Walltime,
138+
command: command.to_string(),
139+
enable_perf,
140+
..Config::test()
141+
}
142+
}
79143

80-
let config = Config {
81-
mode: RunnerMode::Walltime,
82-
command: cmd.to_string(),
83-
enable_perf,
84-
..Config::test()
85-
};
144+
#[rstest::rstest]
145+
#[case(TESTS[0], false)]
146+
#[case(TESTS[0], true)]
147+
#[case(TESTS[1], false)]
148+
#[case(TESTS[1], true)]
149+
#[case(TESTS[2], false)]
150+
#[case(TESTS[2], true)]
151+
#[case(TESTS[3], false)]
152+
#[case(TESTS[3], true)]
153+
#[tokio::test]
154+
async fn test_walltime_executor(#[case] cmd: &str, #[case] enable_perf: bool) {
155+
let (system_info, run_data, _temp_dir) = create_test_setup().await;
156+
let (_permit, executor) = get_walltime_executor().await;
157+
158+
let config = walltime_config(cmd, enable_perf);
159+
executor
160+
.run(&config, &system_info, &run_data, &None)
161+
.await
162+
.unwrap();
163+
}
86164

165+
#[rstest::rstest]
166+
#[case("MY_ENV_VAR", "Hello", ENV_VAR_VALIDATION_SCRIPT, false)]
167+
#[case("MY_ENV_VAR", "Hello", ENV_VAR_VALIDATION_SCRIPT, true)]
168+
#[tokio::test]
169+
async fn test_walltime_executor_with_env(
170+
#[case] env_var: &str,
171+
#[case] env_value: &str,
172+
#[case] cmd: &str,
173+
#[case] enable_perf: bool,
174+
) {
175+
let (system_info, run_data, _temp_dir) = create_test_setup().await;
176+
let (_permit, executor) = get_walltime_executor().await;
177+
178+
temp_env::async_with_vars(&[(env_var, Some(env_value))], async {
179+
let config = walltime_config(cmd, enable_perf);
87180
executor
88181
.run(&config, &system_info, &run_data, &None)
89182
.await
90183
.unwrap();
91-
92-
// Don't execute teardown since the cmds dont use the FIFO to set the integration metadata.
93-
}
184+
})
185+
.await;
94186
}
95187
}

0 commit comments

Comments
 (0)