Skip to content

Commit e63ec79

Browse files
committed
Add native tests workflow and path handling
1 parent 320c613 commit e63ec79

File tree

6 files changed

+136
-47
lines changed

6 files changed

+136
-47
lines changed

.github/workflows/build.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,15 @@ jobs:
3333
- uses: actions/checkout@v4
3434
- name: Run Docker tests
3535
run: cargo test --verbose -F docker-tests
36-
# run: cargo test --verbose -F docker-tests -- --test-threads 1
36+
37+
native-tests:
38+
runs-on: ubuntu-latest
39+
needs: build
40+
41+
steps:
42+
- uses: actions/checkout@v4
43+
- name: Setup Pixi
44+
uses: prefix-dev/setup-pixi@v@v0.9.4
45+
- name: Run Native tests
46+
run: |
47+
cargo test --verbose -F native-tests

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ description = "Command line tool to run various biomolecular structural predicti
88
[features]
99
docker-tests = []
1010
hpc-tests = []
11+
native-tests = []
1112
high-memory-tests = []
12-
all = ["docker-tests", "hpc-tests", "high-memory-tests"]
13+
all = ["docker-tests", "hpc-tests", "native-tests", "high-memory-tests"]
1314

1415
[dependencies]
1516
anyhow = "1.0.100"

src/app/rfdiffusion.rs

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,27 @@ pub fn native_spec(mut app_args: Vec<String>, working_dir: &Path) -> NativeRunSp
2323
const OUTPUT_PREFIX: &str = "inference.output_prefix=";
2424

2525
let mut output_prefix_present = false;
26+
27+
let make_absolute = |path_str: &str| -> String {
28+
let path = PathBuf::from(path_str);
29+
if path.is_absolute() {
30+
path_str.to_string()
31+
} else {
32+
working_dir.join(path).to_string_lossy().into()
33+
}
34+
};
35+
2636
for arg in &mut app_args {
27-
if arg.starts_with(INPUT_PDB_PREFIX) {
28-
let input_pdb = arg.split_at(INPUT_PDB_PREFIX.len()).1;
29-
30-
let input_pdb_path = PathBuf::from(input_pdb);
31-
if !input_pdb_path.is_absolute() {
32-
let abs_input_pdb = working_dir.join(input_pdb_path);
33-
*arg = format!("inference.input_pdb={}", abs_input_pdb.to_str().unwrap());
34-
}
35-
} else if arg.starts_with(OUTPUT_PREFIX) {
36-
let output_prefix = arg.split_at(OUTPUT_PREFIX.len()).1;
37-
38-
let output_prefix_path = PathBuf::from(output_prefix);
39-
if !output_prefix_path.is_absolute() {
40-
let abs_output_prefix = working_dir.join(output_prefix_path);
41-
*arg = format!(
42-
"inference.output_prefix={}",
43-
abs_output_prefix.to_str().unwrap()
44-
);
45-
}
37+
if let Some(input_pdb) = arg.strip_prefix(INPUT_PDB_PREFIX) {
38+
*arg = format!("{INPUT_PDB_PREFIX}{}", make_absolute(input_pdb));
39+
} else if let Some(output_prefix) = arg.strip_prefix(OUTPUT_PREFIX) {
40+
*arg = format!("{OUTPUT_PREFIX}{}", make_absolute(output_prefix));
4641
output_prefix_present = true;
4742
}
4843
}
4944

5045
if !output_prefix_present {
51-
app_args.extend_from_slice(&[format!("{OUTPUT_PREFIX}{}/", working_dir.to_str().unwrap())]);
46+
app_args.push(format!("{OUTPUT_PREFIX}{}/", working_dir.to_string_lossy()));
5247
}
5348

5449
NativeRunSpec::new(include_asset!("pixi/rfdiffusion.toml"), app_args)

src/executor/native.rs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
use std::fs;
2+
13
use anyhow::Result;
24
use anyhow::anyhow;
35
use home::home_dir;
46
use yansi::Paint;
57

8+
use crate::executor::Telemetry;
69
use crate::run;
710
use crate::util::Command;
811
use crate::util::ensure_dir_signature;
@@ -44,14 +47,46 @@ impl Executor {
4447
.collect::<Vec<_>>()
4548
.join(" ");
4649

47-
Command::new("pixi")
50+
let command = Command::new("pixi")
4851
.cd(&pixi_evn_root)
4952
.arg("run")
5053
.arg("execute")
5154
.arg(new_args)
52-
.live()
53-
.exec()?;
54-
55+
.live();
56+
57+
let result = command.call();
58+
59+
let t = Telemetry::new(&self.working_dir);
60+
61+
let logs = format!(
62+
"{command}\nprocess success: {}\n{}\n{}\n{}\n",
63+
result.success, result.stdout, result.stderr, result.stderr
64+
);
65+
66+
fs::write(t.log_file_name(), logs)?;
67+
68+
if !result.success {
69+
eprintln!(
70+
"{}",
71+
"Container {engine} exited with non-zero status"
72+
.bright_red()
73+
.bold()
74+
);
75+
return Err(anyhow::anyhow!(
76+
"Docker container exited with non-zero status"
77+
));
78+
}
79+
80+
println!(
81+
"{}",
82+
format!(
83+
"The exact command line used and full log saved into {:?}\nScratch dir for this run is: {:?}\n",
84+
t.log_file_name(), t.scratch_dir()
85+
)
86+
.blue()
87+
.dim()
88+
);
89+
5590
Ok(())
5691
}
5792

tests/common/macros.rs

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,101 @@
11
#[allow(unused_macros)]
22
macro_rules! engine_tests {
3-
// Handles both cases:
4-
// common::engine_tests!(rfdiffusion);
5-
// common::engine_tests!(rfdiffusion; "high-memory-tests");
6-
// common::engine_tests!(rfdiffusion; "high-memory-tests", "some-awesome-feature");
7-
//
8-
($test_fn:ident $(; $($feature:literal),+ $(,)?)?) => {
9-
::paste::paste! {
3+
// Default: all engines (including none), optional features
4+
($test_fn:ident $(; $($feature:literal),* $(,)?)? ) => {
5+
$crate::common::engine_tests!(
6+
@gen $test_fn;
7+
//engines(docker, singularity, apptainer, none);
8+
engines(docker, singularity, apptainer);
9+
features($($($feature),*)?)
10+
);
11+
};
12+
13+
// Explicit engines override (+ optional features)
14+
($test_fn:ident;
15+
engines($($eng:ident),+ $(,)? )
16+
$(; $($feature:literal),* $(,)?)?
17+
) => {
18+
$crate::common::engine_tests!(
19+
@gen $test_fn;
20+
engines($($eng),+);
21+
features($($($feature),*)?)
22+
);
23+
};
24+
25+
// Normalize: features are passed as ONE token tree: ( ... )
26+
(@gen $test_fn:ident; engines($($eng:ident),+); features $features:tt) => {
27+
$(
28+
$crate::common::engine_tests!(@emit $test_fn; $eng; $features);
29+
)+
30+
};
31+
32+
// ---- Per-engine expansion (re-parse features here) ----
1033

34+
(@emit $test_fn:ident; docker; ($($feature:literal),*) ) => {
35+
::paste::paste! {
1136
#[test]
1237
#[serial_test::serial]
1338
#[cfg_attr(
14-
not(all(
15-
feature = "docker-tests"
16-
$( $(, feature = $feature)*)?
17-
)),
39+
not(all(feature = "docker-tests" $(, feature = $feature)*)),
1840
ignore
1941
)]
2042
fn [<docker_ $test_fn>]() {
21-
common::docker_clear_cache();
43+
$crate::common::docker_clear_cache();
2244
$test_fn("docker");
2345
}
46+
}
47+
};
2448

49+
(@emit $test_fn:ident; singularity; ($($feature:literal),*) ) => {
50+
::paste::paste! {
2551
#[test]
2652
#[serial_test::serial]
2753
#[cfg_attr(
28-
not(all(
29-
feature = "hpc-tests"
30-
$($(, feature = $feature)*)?
31-
)),
54+
not(all(feature = "hpc-tests" $(, feature = $feature)*)),
3255
ignore
3356
)]
3457
fn [<singularity_ $test_fn>]() {
3558
$test_fn("singularity");
3659
}
60+
}
61+
};
3762

63+
(@emit $test_fn:ident; apptainer; ($($feature:literal),*) ) => {
64+
::paste::paste! {
3865
#[test]
3966
#[serial_test::serial]
4067
#[cfg_attr(
41-
not(all(
42-
feature = "hpc-tests"
43-
$($(, feature = $feature)*)?
44-
)),
68+
not(all(feature = "hpc-tests" $(, feature = $feature)*)),
4569
ignore
4670
)]
4771
fn [<apptainer_ $test_fn>]() {
4872
$test_fn("apptainer");
4973
}
5074
}
5175
};
76+
77+
(@emit $test_fn:ident; none; ($($feature:literal),*) ) => {
78+
::paste::paste! {
79+
#[test]
80+
#[serial_test::serial]
81+
#[cfg_attr(
82+
not(all(feature = "native-tests" $(, feature = $feature)*)),
83+
ignore
84+
)]
85+
fn [<native_ $test_fn>]() {
86+
$test_fn("none");
87+
}
88+
}
89+
};
90+
91+
// Nice error for typos / unsupported engines
92+
(@emit $test_fn:ident; $other:ident; $features:tt ) => {
93+
compile_error!(concat!(
94+
"engine_tests!: unknown engine '",
95+
stringify!($other),
96+
"'. Expected: docker, singularity, apptainer, none."
97+
));
98+
};
5299
}
53100

54101
// macro_rules! engine_tests {

tests/rfdiffusion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use assert_fs::TempDir;
33

44
mod common;
55

6-
common::engine_tests!(rfdiffusion; "high-memory-tests");
6+
common::engine_tests!(rfdiffusion; engines(docker, apptainer, singularity, none); "high-memory-tests");
77

88
fn rfdiffusion(engine: &str) {
99
use assert_fs::assert::PathAssert;

0 commit comments

Comments
 (0)