Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Code Coverage

on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
workflow_dispatch:

jobs:
coverage:
name: Code Coverage
runs-on: ubuntu-latest

strategy:
matrix:
feature-set:
- ""
- "--features ml-kem"
- "--features post-quantum"
- "--features ml-kem,post-quantum"

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- name: Install cargo-tarpaulin
run: cargo install cargo-tarpaulin --locked

- name: Run tests with coverage
run: |
if [ -z "${{ matrix.feature-set }}" ]; then
cargo tarpaulin \
--out Xml \
--out Html \
--output-dir coverage \
--timeout 300 \
--fail-under 80
else
cargo tarpaulin \
--features ${{ matrix.feature-set }} \
--out Xml \
--out Html \
--output-dir coverage \
--timeout 300 \
--fail-under 80
fi

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: ./coverage/cobertura.xml
flags: ${{ matrix.feature-set || 'default' }}
name: codecov-${{ matrix.feature-set || 'default' }}
fail_ci_if_error: false

- name: Upload coverage artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report-${{ matrix.feature-set || 'default' }}
path: coverage/
retention-days: 30

11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,14 @@ Thumbs.db

# Test artifacts
test-results/
BRANCH_WORK_SUMMARY.md
COMPARISON.md
COVERAGE_ANALYSIS.md
COVERAGE_GAPS_ANALYSIS.md
COVERAGE_IMPROVEMENTS.md
COVERAGE_TESTS_ADDED.md
FIXES.md
IMPLEMENTATION.md
NEXT_STEPS.md
README_COVERAGE.md
src/NOTES.md
29 changes: 29 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,35 @@ authors = ["thanos vassilakis"]
license = "MIT"
description = "Rust implementation of Bottle protocol - layered message containers with encryption and signatures"
repository = "https://github.com/thanos/rust-bottle"
readme = "README.md"
keywords = ["cryptography", "encryption", "signature", "bottle", "protocol", "security", "privacy"]
categories = ["cryptography", "encoding", "authentication"]
exclude = [
"patches/",
"target/",
"coverage/",
"API.md",
"BRANCH_WORK_SUMMARY.md",
"COMPARISON.md",
"COVERAGE_ANALYSIS.md",
"COVERAGE_GAPS_ANALYSIS.md",
"COVERAGE_IMPROVEMENTS.md",
"COVERAGE_TESTS_ADDED.md",
"FIXES.md",
"IMPLEMENTATION.md",
"NEXT_STEPS.md",
"POST_QUANTUM.md",
"PQC_FEATURE_FLAG.md",
"README_COVERAGE.md",
"scripts/",
"tarpaulin.toml",
"build_rs_cov.profraw",
"src/NOTES.md",
".gitignore",
".git/",
".idea/",
".vscode/",
]

[dependencies]
# Cryptographic primitives
Expand Down
18 changes: 9 additions & 9 deletions POST_QUANTUM.md
Original file line number Diff line number Diff line change
Expand Up @@ -401,25 +401,25 @@ ml-kem = ["pqcrypto-kyber"]

### macOS/ARM (AArch64)

- **ML-DSA**: Works (uses clean dilithium2/3/5 implementations)
- **SLH-DSA**: Works (uses clean sphincsshake256 implementations)
- **ML-KEM**: Compilation fails due to `pqcrypto-kyber` v0.5 bug
- **ML-DSA**: Works (uses clean dilithium2/3/5 implementations)
- **SLH-DSA**: Works (uses clean sphincsshake256 implementations)
- **ML-KEM**: Compilation fails due to `pqcrypto-kyber` v0.5 bug

**Issue**: `pqcrypto-kyber` v0.5.0 has a bug where AVX2 FFI functions are referenced even on AArch64, causing compilation failures. The crate should automatically use the "clean" (generic/portable) implementation on AArch64, but the bug prevents this.

**Workaround**: Use only the `post-quantum` feature (signatures only) on macOS/ARM, or wait for a fix in `pqcrypto-kyber`.

### x86/x86_64

- **ML-DSA**: Works
- **SLH-DSA**: Works
- **ML-KEM**: Works (uses AVX2-optimized implementation if available)
- **ML-DSA**: Works
- **SLH-DSA**: Works
- **ML-KEM**: Works (uses AVX2-optimized implementation if available)

### Other Platforms

- **ML-DSA**: Should work (uses clean implementations)
- **SLH-DSA**: Should work (uses clean implementations)
- **ML-KEM**: ⚠️ May have issues depending on platform
- **ML-DSA**: Should work (uses clean implementations)
- **SLH-DSA**: Should work (uses clean implementations)
- **ML-KEM**: May have issues depending on platform

## Known Limitations

Expand Down
22 changes: 11 additions & 11 deletions scripts/coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

set -e

echo "🔍 Running code coverage analysis for rust-bottle"
echo "Running code coverage analysis for rust-bottle"
echo ""

# Colors for output
Expand All @@ -14,7 +14,7 @@ NC='\033[0m' # No Color

# Check if cargo-tarpaulin is installed
if ! command -v cargo-tarpaulin &> /dev/null; then
echo " cargo-tarpaulin is not installed"
echo "ERROR: cargo-tarpaulin is not installed"
echo " Install it with: cargo install cargo-tarpaulin"
exit 1
fi
Expand All @@ -35,7 +35,7 @@ run_coverage() {
local features=$1
local feature_name=${features:-"default"}

echo -e "${YELLOW}📊 Running coverage with features: ${feature_name}${NC}"
echo -e "${YELLOW}Running coverage with features: ${feature_name}${NC}"

if [ -z "$features" ]; then
cargo tarpaulin \
Expand All @@ -57,10 +57,10 @@ run_coverage() {
fi

if [ $? -eq 0 ]; then
echo -e "${GREEN}Coverage passed for ${feature_name}${NC}"
echo -e "${GREEN}Coverage passed for ${feature_name}${NC}"
echo ""
else
echo -e " Coverage failed for ${feature_name}"
echo -e "ERROR: Coverage failed for ${feature_name}"
echo ""
return 1
fi
Expand All @@ -75,32 +75,32 @@ for features in "${FEATURES[@]}"; do
done

# Generate summary
echo "📈 Coverage Summary"
echo "Coverage Summary"
echo "=================="
echo ""
for features in "${FEATURES[@]}"; do
feature_name=${features:-"default"}
if [ -f "coverage/${feature_name}/cobertura.xml" ]; then
echo " ${feature_name}: Report generated"
echo "SUCCESS: ${feature_name}: Report generated"
echo " HTML: coverage/${feature_name}/tarpaulin-report.html"
echo " XML: coverage/${feature_name}/cobertura.xml"
else
echo " ${feature_name}: No report generated"
echo "ERROR: ${feature_name}: No report generated"
fi
echo ""
done

# Open the default coverage report if on macOS
if [[ "$OSTYPE" == "darwin"* ]] && [ -f "coverage/default/tarpaulin-report.html" ]; then
echo "🌐 Opening coverage report in browser..."
echo "Opening coverage report in browser..."
open "coverage/default/tarpaulin-report.html"
fi

if [ $FAILED -eq 1 ]; then
echo "⚠️ Some coverage runs failed. Check the output above for details."
echo "WARNING: Some coverage runs failed. Check the output above for details."
exit 1
else
echo -e "${GREEN}All coverage reports generated successfully!${NC}"
echo -e "${GREEN}All coverage reports generated successfully!${NC}"
exit 0
fi

Expand Down
14 changes: 7 additions & 7 deletions tests/coverage_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2895,16 +2895,13 @@ fn test_decrypt_aes_gcm_success() {
// ============================================================================
// Kyber1024 Module Coverage Tests (patches/pqcrypto-kyber-0.5.0/src/kyber1024.rs)
// ============================================================================
// NOTE: These tests are commented out because pqcrypto_kyber is not available as a dependency.
// The kyber1024 module is in the patches directory and may not be directly accessible.
// To enable these tests:
// 1. Add pqcrypto-kyber as a dependency (or path dependency to patches/pqcrypto-kyber-0.5.0)
// 2. Uncomment the tests below
// NOTE: These tests require the "pqcrypto-kyber" feature to be enabled.
// To run these tests: cargo test --features pqcrypto-kyber --test coverage
//
// Lines to cover: 120-125, 127, 129, 134-139, 141, 157-159, 161-166, 169, 172,
// 178-180, 182-186, 188, 191, 206-213, 216, 218, 224-228, 230

/*
#[cfg(feature = "pqcrypto-kyber")]
#[test]
fn test_kyber1024_keypair_portable() {
// Test lines 120-125, 127, 129: keypair_portable function
Expand Down Expand Up @@ -2977,6 +2974,7 @@ fn test_kyber1024_decapsulate_portable() {
assert_eq!(ss2.as_bytes().len(), kyber1024::shared_secret_bytes());
}

#[cfg(feature = "pqcrypto-kyber")]
#[test]
fn test_kyber1024_keypair_multiple_times() {
// Test to ensure keypair_portable is exercised multiple times
Expand All @@ -2996,6 +2994,7 @@ fn test_kyber1024_keypair_multiple_times() {
}
}

#[cfg(feature = "pqcrypto-kyber")]
#[test]
fn test_kyber1024_encapsulate_decapsulate_round_trip() {
// Comprehensive test to exercise all portable functions
Expand Down Expand Up @@ -3023,6 +3022,7 @@ fn test_kyber1024_encapsulate_decapsulate_round_trip() {
}
}

#[cfg(feature = "pqcrypto-kyber")]
#[test]
fn test_kyber1024_from_bytes_error_paths() {
// Test error paths in from_bytes (part of the simple_struct macro)
Expand All @@ -3047,6 +3047,7 @@ fn test_kyber1024_from_bytes_error_paths() {
assert!(result4.is_err());
}

#[cfg(feature = "pqcrypto-kyber")]
#[test]
fn test_kyber1024_from_bytes_success() {
// Test successful from_bytes paths
Expand Down Expand Up @@ -3078,5 +3079,4 @@ fn test_kyber1024_from_bytes_success() {
// But we can verify the size is correct
assert_eq!(ss.as_bytes().len(), ss_expected.as_bytes().len());
}
*/

Loading