diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index dc1049d..e8515ad 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -57,10 +57,8 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - - name: List files - run: | - pwd - ls + with: + submodules: true - uses: dtolnay/rust-toolchain@stable with: components: llvm-tools-preview @@ -70,8 +68,8 @@ jobs: - uses: Swatinem/rust-cache@v2 with: key: ${{ matrix.os }} - - run: cargo build # tests need prebuild so - - run: cargo llvm-cov nextest --lcov --output-path lcov.info + - run: cargo build # tests need prebuild .so for tests + - run: cargo llvm-cov nextest --no-fail-fast --lcov --output-path lcov.info - run: cargo test --doc - name: Upload coverage data to codecov uses: codecov/codecov-action@v3 diff --git a/.gitmodules b/.gitmodules index eb36581..522fb42 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,3 @@ [submodule "rcrypto-sys/tests/c/unity"] path = rcrypto-sys/tests/c/unity url = https://github.com/ThrowTheSwitch/Unity.git - shallow = true diff --git a/rcrypto-sys/.clangd b/rcrypto-sys/.clangd new file mode 100644 index 0000000..624ce27 --- /dev/null +++ b/rcrypto-sys/.clangd @@ -0,0 +1,8 @@ +CompileFlags: + Add: + - "-I../" + - "-I." + - "-Itests/c" + - "-Ic" + - "-Itests/c/unity" + - "-Ic/unity" diff --git a/rcrypto-sys/Cargo.toml b/rcrypto-sys/Cargo.toml index 7931665..76ef813 100644 --- a/rcrypto-sys/Cargo.toml +++ b/rcrypto-sys/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [lib] -# crate-type = ["cdylib"] # FIXME: how do we make this cdylib only? +# https://github.com/rust-lang/cargo/issues/9096 crate-type = ["cdylib", "lib"] [dependencies] diff --git a/rcrypto-sys/build.rs b/rcrypto-sys/build.rs index 21b8401..e9e83cf 100644 --- a/rcrypto-sys/build.rs +++ b/rcrypto-sys/build.rs @@ -11,7 +11,6 @@ fn main() { const TEST_PREFIX: &str = "// autogenerated file, do not edit manually // one test is generated for each `.c` file - "; #[cfg(windows)] @@ -26,81 +25,10 @@ fn update_tests() { let out_dir = PathBuf::from(&env::var("OUT_DIR").unwrap()); let out_file = out_dir.join("auto_suite.rs"); let test_dir = crate_dir.join("tests"); - // println!("cargo:rerun-if-changed={}", suite_dir.to_string_lossy()); let test_paths = fs::read_dir(&test_dir).unwrap(); let mut to_write = TEST_PREFIX.to_owned(); - indoc::writedoc!( - to_write, - " - // use std::io::prelude::*; - use std::process::Command; - use std::sync::Once; - - static MAKE: Once = Once::new(); - - fn run_setup() {{ - MAKE.call_once(|| {{ - let mut cmd = Command::new(\"make\"); - cmd.args([\"-C\", \"{test_dir}\"].as_slice()); - cmd.env(\"OUT_DIR\", \"{out_dir}\"); - run_cmd_else_quit(&mut cmd, \"makefile\"); - }}) - }} - - /// Run a command, if it fails print its output - fn run_cmd_else_quit(cmd: &mut Command, fname: &str) {{ - let out = cmd - .output() - .unwrap_or_else(|e| panic!(\"failed to run command {{cmd:?}}: {{e}}\")); - - let stdout = String::from_utf8_lossy(&out.stdout); - let stderr = String::from_utf8_lossy(&out.stderr); - - let combined = format!(\"{{stdout}}{{stderr}}\"); - let mut has_failures = false; - - if combined.contains(\"IGNORE\") || - combined.contains(\"FAIL\") || - combined.contains(\"PASS\") - {{ - // using output from unity, format it nicely - println!(\" -------- unity ignores --------\"); - combined.lines() - .filter(|line| line.contains(\"IGNORE\")) - .for_each(|line| println!(\" {{line}}\")); - - println!(\n\" -------- unity failures --------\"); - combined.lines() - .filter(|line| line.contains(\"FAIL\")) - .for_each(|line| {{ - println!(\" {{line}}\"); - has_failures = true; - }}); - - println!(\n\" -------- unity passed --------\"); - combined.lines() - .filter(|line| line.contains(\"PASS\")) - .for_each(|line| println!(\" {{line}}\")); - }} else {{ - // For other failures, just propegate the output - println!(\"{{stdout}}\"); - eprintln!(\"{{stderr}}\"); - }} - - println!(); - - if !out.status.success() || has_failures {{ - panic!(\"{{fname}} failed with status {{}}\", out.status); - }} - }} - ", - test_dir = test_dir.to_string_lossy(), - out_dir = out_dir.to_string_lossy(), - ) - .unwrap(); - for path in test_paths { let path = path.unwrap().path(); let fname = path.file_name().unwrap().to_string_lossy(); diff --git a/rcrypto-sys/tests/Makefile b/rcrypto-sys/tests/Makefile index 9f6a0f9..5c89708 100644 --- a/rcrypto-sys/tests/Makefile +++ b/rcrypto-sys/tests/Makefile @@ -26,6 +26,7 @@ else target_extension = out endif +.PHONY: check-submodules .PHONY: clean .PHONY: build @@ -56,13 +57,22 @@ ldflags = -L$(dir_sharedlib) -l$(lib_name) $(LDFLAGS) test_exe_files = $(patsubst $(dir_tests)%.c,$(dir_testout)test_%.$(target_extension),$(test_src_files)) build_paths = $(dir_build) $(dir_testout) -build: $(build_paths) $(test_exe_files) +.check-submodules: + @if git submodule status | egrep -q '^[-+]' ; then \ + echo "ERROR: submodules need to be initialized"; \ + else \ + echo "submodules up to date"; \ + fi + +build: .check-submodules $(build_paths) $(test_exe_files) @echo generating C output to $(outdir) # make all test executables $(dir_testout)test_%.$(target_extension): $(dir_build)unity.o \ $(dir_build)test_framework.o $(dir_build)test_%.o - $(link) $(ldflags) -o $@ $^ + pwd + ls -l $(dir_sharedlib) + $(link) -o $@ $^ $(ldflags) # make all test object files $(dir_build)test_%.o:: $(dir_tests)%.c diff --git a/rcrypto-sys/tests/c_runner.rs b/rcrypto-sys/tests/c_runner.rs index 0679458..717e9fa 100644 --- a/rcrypto-sys/tests/c_runner.rs +++ b/rcrypto-sys/tests/c_runner.rs @@ -1,2 +1,82 @@ +// Setup lives in this file + +use std::env; +use std::path::Path; +use std::process::{Command, Stdio}; +use std::sync::Once; + +static MAKE: Once = Once::new(); + +fn run_setup() { + let out_dir = env!("OUT_DIR"); + let crate_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let test_dir = crate_dir.join("tests"); + + MAKE.call_once(|| { + println!("using output directory {out_dir}"); + let mut cmd = Command::new("make"); + cmd.args( + [ + "-C", + &test_dir.to_string_lossy(), + &format!("OUT_DIR={out_dir}"), + ] + .as_slice(), + ); + cmd.stdout(Stdio::inherit()); + cmd.stderr(Stdio::inherit()); + let out = cmd.output().expect("failed to run Makefile"); + assert!(out.stdout.is_empty()); + assert!(out.stderr.is_empty()); + }) +} + +/// Run a command, if it fails print its output +fn run_cmd_else_quit(cmd: &mut Command, fname: &str) { + let out = cmd + .output() + .unwrap_or_else(|e| panic!("failed to run command {cmd:?}: {e}")); + + let stdout = String::from_utf8_lossy(&out.stdout); + let stderr = String::from_utf8_lossy(&out.stderr); + + let combined = format!("{stdout}{stderr}"); + let mut has_failures = false; + + if combined.contains("IGNORE") || combined.contains("FAIL") || combined.contains("PASS") { + // using output from unity, format it nicely + println!("> -------- unity ignored --------"); + combined + .lines() + .filter(|line| line.contains("IGNORE")) + .for_each(|line| println!("> {line}")); + + println!("\n> -------- unity failures --------"); + combined + .lines() + .filter(|line| line.contains("FAIL")) + .for_each(|line| { + println!("> {line}"); + has_failures = true; + }); + + println!("\n> -------- unity passed --------"); + combined + .lines() + .filter(|line| line.contains("PASS")) + .for_each(|line| println!("> {line}")); + } else { + // For other failures, just propegate the output + println!("{stdout}"); + eprintln!("{stderr}"); + } + + println!(); + + if !out.status.success() || has_failures { + panic!("{fname} failed with status {}", out.status); + } +} + // include tests generated by `build.rs`, C test suite runner include!(concat!(env!("OUT_DIR"), "/auto_suite.rs"));