diff --git a/.codecov.yaml b/.codecov.yaml new file mode 100644 index 00000000..db335665 --- /dev/null +++ b/.codecov.yaml @@ -0,0 +1,9 @@ +# https://docs.codecov.com/docs/codecovyml-reference +# curl -X POST --data-binary @.codecov.yaml https://codecov.io/validate +coverage: + status: + patch: + default: + target: 100% + threshold: 0% + informational: true diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index cc76c211..ea3650ed 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -24,10 +24,15 @@ jobs: RUST_BACKTRACE: full run: | mkdir -p tests/.tmp - cargo llvm-cov --codecov --output-path target/llvm-cov-target/codecov.json -- --nocapture + cargo llvm-cov \ + --ignore-filename-regex "bin/.*|lib\.rs" \ + --cobertura \ + --output-path target/llvm-cov-target/cobertura.xml \ + -- \ + --nocapture - name: Upload to codecov.io uses: codecov/codecov-action@v5 with: fail_ci_if_error: true - files: target/llvm-cov-target/codecov.json + files: target/llvm-cov-target/cobertura.xml verbose: true diff --git a/README.md b/README.md index dbfb983d..ec7cc17c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ [![orcapod API docs](https://img.shields.io/website?url=https://walkerlab.github.io/orcapod/&label=docs) ](https://walkerlab.github.io/orcapod/) +[![codecov](https://codecov.io/github/walkerlab/orcapod/graph/badge.svg)](https://codecov.io/github/walkerlab/orcapod) # orcapod @@ -9,12 +10,13 @@ ```bash #!/bin/bash -set -e # stop early on non-zero exit +set -e # fail early on non-zero exit cargo clippy --all-targets -- -D warnings # syntax and style tests cargo fmt --check # formatting test -cargo llvm-cov -- --nocapture # integration tests w/ stdout coverage summary -cargo llvm-cov --html -- --nocapture # integration tests w/ HTML coverage report (target/llvm-cov/html/index.html) -cargo llvm-cov --codecov --output-path target/llvm-cov-target/codecov.json -- --nocapture # integration tests w/ coverage report prepared for codecov +cargo llvm-cov --ignore-filename-regex "bin/.*|lib\.rs" -- --nocapture # integration tests w/ stdout coverage summary +cargo llvm-cov --ignore-filename-regex "bin/.*|lib\.rs" --html -- --nocapture # integration tests w/ HTML coverage report (target/llvm-cov/html/index.html) +cargo llvm-cov --ignore-filename-regex "bin/.*|lib\.rs" --codecov --output-path target/llvm-cov-target/codecov.json -- --nocapture # integration tests w/ codecov coverage report +cargo llvm-cov --ignore-filename-regex "bin/.*|lib\.rs" --cobertura --output-path target/llvm-cov-target/cobertura.xml -- --nocapture # integration tests w/ cobertura coverage report ``` ## Docs diff --git a/tests/error.rs b/tests/error.rs index 835a16b1..537ee374 100644 --- a/tests/error.rs +++ b/tests/error.rs @@ -1,19 +1,21 @@ -#![expect(missing_docs, clippy::expect_used, reason = "OK in tests.")] +#![expect(missing_docs, clippy::panic_in_result_fn, reason = "OK in tests.")] pub mod fixture; use fixture::{NAMESPACE_LOOKUP_READ_ONLY, pod_job_style}; use glob::glob; -use orcapod::uniffi::{ - error::{OrcaError, Result}, - orchestrator::{Orchestrator as _, docker::LocalDockerOrchestrator}, +use orcapod::{ + core::crypto::hash_file, + uniffi::{ + error::{OrcaError, Result}, + orchestrator::{Orchestrator as _, docker::LocalDockerOrchestrator}, + }, }; use serde_json; use serde_yaml; -use std::{collections::HashMap, fmt, fs, path::PathBuf, result}; +use std::{collections::HashMap, fs, path::PathBuf}; -fn check>(value: result::Result) -> String { - let error: OrcaError = value.expect_err("Did not return an expected error.").into(); - format!("{error:?}") +fn contains_debug(error: impl Into) -> bool { + !format!("{:?}", error.into()).is_empty() } #[test] @@ -21,31 +23,68 @@ fn external_bollard() -> Result<()> { let orch = LocalDockerOrchestrator::new()?; let mut pod_job = pod_job_style(&NAMESPACE_LOOKUP_READ_ONLY)?; pod_job.pod.image = "nonexistent_image".to_owned(); - check(orch.start_blocking(&NAMESPACE_LOOKUP_READ_ONLY, &pod_job)); + assert!( + orch.start_blocking(&NAMESPACE_LOOKUP_READ_ONLY, &pod_job) + .is_err_and(contains_debug), + "Did not raise a bollard error." + ); Ok(()) } #[test] fn external_glob() { - check(glob("a**/b")); + assert!( + glob("a**/b").is_err_and(contains_debug), + "Did not raise a glob error." + ); } #[test] fn external_io() { - check(fs::read_to_string("nonexistent_file.txt")); + assert!( + fs::read_to_string("nonexistent_file.txt").is_err_and(contains_debug), + "Did not raise an I/O error." + ); } #[test] fn external_path_prefix() { - check(PathBuf::from("/fake/path").strip_prefix("/missing/path")); + assert!( + PathBuf::from("/fake/path") + .strip_prefix("/missing/path") + .is_err_and(contains_debug), + "Did not raise a path prefix error." + ); } #[test] fn external_json() { - check(serde_json::from_str::>("{")); + assert!( + serde_json::from_str::>("{").is_err_and(contains_debug), + "Did not raise a serde json error." + ); } #[test] fn external_yaml() { - check(serde_yaml::from_str::>(":")); + assert!( + serde_yaml::from_str::>(":").is_err_and(contains_debug), + "Did not raise a serde yaml error." + ); +} + +#[test] +fn internal_invalid_filepath() { + assert!( + hash_file("nonexistent_file.txt").is_err_and(contains_debug), + "Did not raise an invalid filepath error." + ); +} + +#[test] +fn internal_key_missing() { + assert!( + pod_job_style(&HashMap::new()).is_err_and(contains_debug), + "Did not raise a key missing error." + ); } diff --git a/tests/orchestrator.rs b/tests/orchestrator.rs index ad455f46..fa4c9620 100644 --- a/tests/orchestrator.rs +++ b/tests/orchestrator.rs @@ -1,9 +1,4 @@ -#![expect( - clippy::expect_used, - missing_docs, - clippy::panic_in_result_fn, - reason = "OK in tests." -)] +#![expect(missing_docs, clippy::panic_in_result_fn, reason = "OK in tests.")] pub mod fixture; use fixture::{TestContainerImage, TestDirs, container_image_style, pod_job_style}; @@ -75,9 +70,8 @@ where assert!( orchestrator .get_info_blocking(&pod_run) - .expect_err("Unexpectedly succeeded.") - .is_purged_pod_run(), - "Returned a different OrcaError than one expected when getting info of a purged pod run." + .is_err_and(|error| error.is_purged_pod_run() && !format!("{error:?}").is_empty()), + "Did not raise a purged pod run error." ); Ok(()) } diff --git a/tests/store.rs b/tests/store.rs index 3b52d989..782140c0 100644 --- a/tests/store.rs +++ b/tests/store.rs @@ -223,9 +223,8 @@ fn pod_annotation_delete() -> Result<()> { assert!( store .delete_annotation::("style-transfer", "9.9.9") - .expect_err("Unexpectedly succeeded.") - .is_invalid_annotation(), - "Returned a different OrcaError than one expected when deleting an invalid annotation." + .is_err_and(|error| error.is_invalid_annotation() && !format!("{error:?}").is_empty()), + "Did not raise an invalid annotation error." ); Ok(()) }