From 2a88f3db98921074554a4de5ece2a30e72c4f192 Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:13:16 +1200 Subject: [PATCH 01/10] ci: add test coverage via cargo-llvm-cov Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 20 ++++++++++++++++++++ Makefile | 25 ++++++++++++++++++------- README.md | 1 + docs/02-test-coverage.md | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 docs/02-test-coverage.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2034b0..757bec9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,3 +36,23 @@ jobs: grep -E '^test result:|^running' test-output.txt >> "$GITHUB_STEP_SUMMARY" || true echo '```' >> "$GITHUB_STEP_SUMMARY" fi + + coverage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@stable + with: + components: llvm-tools-preview + - uses: Swatinem/rust-cache@v2 + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@cargo-llvm-cov + - name: Generate coverage report + run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info + - name: Upload to Codecov + uses: codecov/codecov-action@v5 + with: + files: lcov.info + fail_ci_if_error: true + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/Makefile b/Makefile index 479dcff..5adecb4 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,15 @@ -.PHONY: help check test fmt lint doc ci +.PHONY: help check test fmt lint doc ci cov install-dev help: @echo "Available targets:" - @echo " check Check workspace compiles" - @echo " test Run all tests" - @echo " fmt Format code" - @echo " lint Run clippy with warnings as errors" - @echo " doc Build and open docs in browser" - @echo " ci Run all CI checks locally (fmt, clippy, test, doc)" + @echo " check Check workspace compiles" + @echo " test Run all tests" + @echo " fmt Format code" + @echo " lint Run clippy with warnings as errors" + @echo " doc Build and open docs in browser" + @echo " cov Generate HTML coverage report and open it" + @echo " ci Run all CI checks locally (fmt, clippy, test, doc)" + @echo " install-dev Install local dev tools (cargo-llvm-cov)" # Check workspace compiles check: @@ -29,6 +31,15 @@ lint: doc: cargo doc --no-deps -p wavekat-core --all-features --open +# Install local dev tools (run once after cloning) +install-dev: + rustup component add llvm-tools-preview + cargo install cargo-llvm-cov + +# Generate HTML coverage report and open it in the browser +cov: + cargo llvm-cov --all-features --open + # Run all CI checks locally (mirrors .github/workflows/ci.yml) ci: cargo fmt --all -- --check diff --git a/README.md b/README.md index f0d881b..3251d56 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![Crates.io](https://img.shields.io/crates/v/wavekat-core.svg)](https://crates.io/crates/wavekat-core) [![docs.rs](https://docs.rs/wavekat-core/badge.svg)](https://docs.rs/wavekat-core) +[![codecov](https://codecov.io/gh/wavekat/wavekat-core/branch/main/graph/badge.svg)](https://codecov.io/gh/wavekat/wavekat-core) Shared types for the WaveKat audio processing ecosystem. diff --git a/docs/02-test-coverage.md b/docs/02-test-coverage.md new file mode 100644 index 0000000..342b26e --- /dev/null +++ b/docs/02-test-coverage.md @@ -0,0 +1,37 @@ +# 02 — Test Coverage + +## Overview + +Code coverage is measured on every CI run using [`cargo-llvm-cov`](https://github.com/taiki-e/cargo-llvm-cov) and reported to [Codecov](https://codecov.io/gh/wavekat/wavekat-core). + +## How It Works + +The `coverage` job in `.github/workflows/ci.yml`: + +1. Installs `cargo-llvm-cov` via [`taiki-e/install-action`](https://github.com/taiki-e/install-action). +2. Runs the full test suite with LLVM instrumentation across all features: + ```sh + cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info + ``` +3. Uploads the LCOV report to Codecov. + +## Viewing Coverage + +- **Badge** — shown in `README.md`, reflects the latest `main` branch coverage. +- **Codecov dashboard** — `https://codecov.io/gh/wavekat/wavekat-core` for line-by-line detail and PR diff coverage. + +## Setup (one-time) + +1. Sign in to [codecov.io](https://codecov.io) with your GitHub account. +2. Enable the `wavekat/wavekat-core` repository. +3. Add the `CODECOV_TOKEN` secret to the GitHub repository settings. + +## Running Locally + +```sh +# Install dev tools once after cloning +make install-dev + +# Generate an HTML report and open it +make cov +``` From b114624b93472440a50d6e6f5b2da6d4089b323d Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:17:40 +1200 Subject: [PATCH 02/10] ci: add codecov.yml for coverage checks and PR comments Co-Authored-By: Claude Sonnet 4.6 --- codecov.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..6e99a73 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,13 @@ +coverage: + status: + project: + default: + target: auto # must not drop below current coverage + threshold: 1% # allow up to 1% drop before failing + patch: + default: + target: 80% # new code in PRs must be at least 80% covered + +comment: + layout: "reach,diff,flags,tree" + behavior: default # post once, update on new commits From 9689c9c73c183b09fba349fc26675e74b8bf994d Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:28:07 +1200 Subject: [PATCH 03/10] chore: add cov-report target to Makefile Co-Authored-By: Claude Sonnet 4.6 --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5adecb4..62cb332 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help check test fmt lint doc ci cov install-dev +.PHONY: help check test fmt lint doc ci cov cov-report install-dev help: @echo "Available targets:" @@ -8,6 +8,7 @@ help: @echo " lint Run clippy with warnings as errors" @echo " doc Build and open docs in browser" @echo " cov Generate HTML coverage report and open it" + @echo " cov-report Print coverage summary as text (paste into Claude Code)" @echo " ci Run all CI checks locally (fmt, clippy, test, doc)" @echo " install-dev Install local dev tools (cargo-llvm-cov)" @@ -40,6 +41,10 @@ install-dev: cov: cargo llvm-cov --all-features --open +# Print uncovered lines only (paste into Claude Code to write tests) +cov-report: + cargo llvm-cov --all-features --text 2>/dev/null | grep -E '\|[[:space:]]+0\|' + # Run all CI checks locally (mirrors .github/workflows/ci.yml) ci: cargo fmt --all -- --check From 5e19100696c725058822157dacf6376b04cb30f6 Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:28:40 +1200 Subject: [PATCH 04/10] test: cover Vec/array IntoSamples impls Co-Authored-By: Claude Sonnet 4.6 --- crates/wavekat-core/src/audio.rs | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crates/wavekat-core/src/audio.rs b/crates/wavekat-core/src/audio.rs index 2b180b7..d521573 100644 --- a/crates/wavekat-core/src/audio.rs +++ b/crates/wavekat-core/src/audio.rs @@ -311,4 +311,42 @@ mod tests { assert_eq!(frame.samples().as_ptr(), ptr); assert_eq!(frame.sample_rate(), 24000); } + + #[test] + fn into_samples_vec_f32() { + let samples = vec![0.1f32, -0.2, 0.3]; + let frame = AudioFrame::new(&samples, 16000); + assert!(matches!(frame.samples, Cow::Borrowed(_))); + assert_eq!(frame.samples(), &[0.1, -0.2, 0.3]); + } + + #[test] + fn into_samples_array_f32() { + let samples = [0.1f32, -0.2, 0.3]; + let frame = AudioFrame::new(&samples, 16000); + assert!(matches!(frame.samples, Cow::Borrowed(_))); + assert_eq!(frame.samples(), &[0.1, -0.2, 0.3]); + } + + #[test] + fn into_samples_vec_i16() { + let samples: Vec = vec![0, 16384, i16::MIN]; + let frame = AudioFrame::new(&samples, 16000); + assert!(matches!(frame.samples, Cow::Owned(_))); + let s = frame.samples(); + assert!((s[0] - 0.0).abs() < f32::EPSILON); + assert!((s[1] - 0.5).abs() < 0.001); + assert!((s[2] - -1.0).abs() < f32::EPSILON); + } + + #[test] + fn into_samples_array_i16() { + let samples: [i16; 3] = [0, 16384, i16::MIN]; + let frame = AudioFrame::new(&samples, 16000); + assert!(matches!(frame.samples, Cow::Owned(_))); + let s = frame.samples(); + assert!((s[0] - 0.0).abs() < f32::EPSILON); + assert!((s[1] - 0.5).abs() < 0.001); + assert!((s[2] - -1.0).abs() < f32::EPSILON); + } } From e594235fc4b12ef652d51a9500658fa6c85ab780 Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:30:49 +1200 Subject: [PATCH 05/10] ci: print coverage summary to Actions job summary Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 757bec9..a8ec316 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,3 +56,10 @@ jobs: fail_ci_if_error: true env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - name: Job summary + if: always() + run: | + echo "## Coverage" >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + cargo llvm-cov report --text --summary-only 2>/dev/null >> "$GITHUB_STEP_SUMMARY" || true + echo '```' >> "$GITHUB_STEP_SUMMARY" From 4cbe12ece8b0697e7ab8273a7fe5978baa341061 Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:33:04 +1200 Subject: [PATCH 06/10] ci: fix coverage summary to show only TOTAL line Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8ec316..ba97daf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,5 +61,5 @@ jobs: run: | echo "## Coverage" >> "$GITHUB_STEP_SUMMARY" echo '```' >> "$GITHUB_STEP_SUMMARY" - cargo llvm-cov report --text --summary-only 2>/dev/null >> "$GITHUB_STEP_SUMMARY" || true + cargo llvm-cov report --text 2>/dev/null | grep '^TOTAL' >> "$GITHUB_STEP_SUMMARY" || true echo '```' >> "$GITHUB_STEP_SUMMARY" From 817658aec1988bc2ce2e6920fc7f3fb6f126c3d8 Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:35:17 +1200 Subject: [PATCH 07/10] ci: fix coverage summary using report --summary-only Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba97daf..1477917 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,5 +61,5 @@ jobs: run: | echo "## Coverage" >> "$GITHUB_STEP_SUMMARY" echo '```' >> "$GITHUB_STEP_SUMMARY" - cargo llvm-cov report --text 2>/dev/null | grep '^TOTAL' >> "$GITHUB_STEP_SUMMARY" || true + cargo llvm-cov report --summary-only 2>/dev/null >> "$GITHUB_STEP_SUMMARY" || true echo '```' >> "$GITHUB_STEP_SUMMARY" From 580569be44b2f88bcb9c8009da386d8a43565237 Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:41:19 +1200 Subject: [PATCH 08/10] chore: ignore lcov.info Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 96ef6c0..32a86fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +lcov.info From fcc215dcfe542d2ce1068d30cc00648633b46f2d Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:43:54 +1200 Subject: [PATCH 09/10] chore: handle no uncovered lines in cov-report target Co-Authored-By: Claude Sonnet 4.6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 62cb332..aa6a5ee 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ cov: # Print uncovered lines only (paste into Claude Code to write tests) cov-report: - cargo llvm-cov --all-features --text 2>/dev/null | grep -E '\|[[:space:]]+0\|' + @cargo llvm-cov --all-features --text 2>/dev/null | grep -E '\|[[:space:]]+0\|' || echo "No uncovered lines." # Run all CI checks locally (mirrors .github/workflows/ci.yml) ci: From be6606b4ca669e9708f56fc2ba603ceb5312de30 Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Tue, 7 Apr 2026 10:47:30 +1200 Subject: [PATCH 10/10] chore: add cov-regions target for uncovered region inspection Co-Authored-By: Claude Sonnet 4.6 --- Makefile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index aa6a5ee..55f62ea 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help check test fmt lint doc ci cov cov-report install-dev +.PHONY: help check test fmt lint doc ci cov cov-report cov-regions install-dev help: @echo "Available targets:" @@ -8,7 +8,8 @@ help: @echo " lint Run clippy with warnings as errors" @echo " doc Build and open docs in browser" @echo " cov Generate HTML coverage report and open it" - @echo " cov-report Print coverage summary as text (paste into Claude Code)" + @echo " cov-report Print uncovered lines" + @echo " cov-regions Print uncovered regions with context" @echo " ci Run all CI checks locally (fmt, clippy, test, doc)" @echo " install-dev Install local dev tools (cargo-llvm-cov)" @@ -45,6 +46,10 @@ cov: cov-report: @cargo llvm-cov --all-features --text 2>/dev/null | grep -E '\|[[:space:]]+0\|' || echo "No uncovered lines." +# Print uncovered regions with source context (paste into Claude Code to write tests) +cov-regions: + @cargo llvm-cov --all-features --text 2>/dev/null | grep -B1 '\^0' || echo "No uncovered regions." + # Run all CI checks locally (mirrors .github/workflows/ci.yml) ci: cargo fmt --all -- --check