Testing and CI Pipeline

Relevant source files

This document covers the automated testing infrastructure and continuous integration setup for the kspin crate. The testing and CI pipeline ensures code quality, compatibility across multiple target platforms, and automated documentation deployment.

For information about manually building the crate and configuring development environments, see Build System and Feature Flags and Development Environment Setup.

CI Pipeline Architecture

The kspin crate uses GitHub Actions for continuous integration, configured through a single workflow file that handles both testing and documentation deployment. The pipeline is designed to validate the crate across multiple embedded and general-purpose target platforms.

CI Pipeline Overview

flowchart TD
subgraph subGraph3["Doc Job Steps"]
    DocCheckout["actions/checkout@v4"]
    DocRust["dtolnay/rust-toolchain@nightly"]
    BuildDocs["cargo doc --no-deps --all-features"]
    Deploy["JamesIves/github-pages-deploy-action@v4"]
end
subgraph subGraph2["CI Job Steps"]
    Checkout["actions/checkout@v4"]
    InstallHack["taiki-e/install-action@cargo-hack"]
    SetupRust["dtolnay/rust-toolchain@nightly"]
    CheckVersion["rustc --version --verbose"]
    Format["cargo fmt --all -- --check"]
    Clippy["cargo hack clippy"]
    Build["cargo hack build"]
    Test["cargo hack test"]
end
subgraph subGraph1["GitHub Actions Workflow"]
    CIJob["ci jobTesting & Quality"]
    DocJob["doc jobDocumentation"]
end
subgraph subGraph0["Trigger Events"]
    Push["push events"]
    PR["pull_request events"]
end

Build --> Test
BuildDocs --> Deploy
CIJob --> Checkout
CheckVersion --> Format
Checkout --> InstallHack
Clippy --> Build
DocCheckout --> DocRust
DocJob --> DocCheckout
DocRust --> BuildDocs
Format --> Clippy
InstallHack --> SetupRust
PR --> CIJob
PR --> DocJob
Push --> CIJob
Push --> DocJob
SetupRust --> CheckVersion

Sources: .github/workflows/ci.yml(L1 - L57) 

Build Matrix Strategy

The CI pipeline uses a matrix build strategy to validate the codebase across multiple target platforms and feature combinations. This ensures compatibility with the diverse environments where kernel spinlocks are typically deployed.

ComponentConfiguration
Runnerubuntu-latest
Rust Toolchainnightly
Required Componentsrust-src,clippy,rustfmt
Target Platforms4 targets (see below)
Failure Strategyfail-fast: false

Target Platform Matrix

flowchart TD
subgraph subGraph1["Target Platforms"]
    LinuxGNU["x86_64-unknown-linux-gnuStandard Linux userspace"]
    x86None["x86_64-unknown-noneBare metal x86_64"]
    RISCV["riscv64gc-unknown-none-elfRISC-V bare metal"]
    ARM["aarch64-unknown-none-softfloatARM64 bare metal"]
end
subgraph subGraph0["Matrix Strategy"]
    Matrix["matrix.targets"]
end
subgraph subGraph2["Feature Testing"]
    EachFeature["--each-feature flagTests all feature combinations"]
    SMPFeature["smp featureMulti-core vs single-core"]
end

EachFeature --> SMPFeature
Matrix --> ARM
Matrix --> LinuxGNU
Matrix --> RISCV
Matrix --> x86None

The cargo-hack tool is used with the --each-feature flag to test all possible feature combinations across all target platforms, ensuring that feature-conditional compilation works correctly.

Sources: .github/workflows/ci.yml(L8 - L20)  .github/workflows/ci.yml(L26 - L31) 

Quality Assurance Pipeline

The CI pipeline enforces code quality through multiple automated checks that must pass before code can be merged.

Quality Check Sequence

sequenceDiagram
    participant GitHubActions as "GitHub Actions"
    participant RustToolchain as "Rust Toolchain"
    participant cargohack as "cargo-hack"
    participant TargetPlatform as "Target Platform"

    GitHubActions ->> RustToolchain: Setup nightly toolchain
    RustToolchain ->> GitHubActions: Install rust-src, clippy, rustfmt
    Note over GitHubActions,TargetPlatform: For each target in matrix
    GitHubActions ->> RustToolchain: cargo fmt --all -- --check
    RustToolchain ->> GitHubActions: ✓ Code formatting validated
    GitHubActions ->> cargohack: cargo hack clippy --target <target> --each-feature
    cargohack ->> TargetPlatform: Run clippy for each feature combination
    TargetPlatform ->> cargohack: ✓ No warnings (-D warnings)
    cargohack ->> GitHubActions: ✓ Linting complete
    GitHubActions ->> cargohack: cargo hack build --target <target> --each-feature
    cargohack ->> TargetPlatform: Build each feature combination
    TargetPlatform ->> cargohack: ✓ Successful build
    cargohack ->> GitHubActions: ✓ Build complete

Code Formatting

  • Tool: cargo fmt
  • Enforcement: --check flag ensures CI fails if code is not properly formatted
  • Scope: All files (--all flag)

Linting

  • Tool: cargo clippy
  • Configuration: Treats all warnings as errors (-D warnings)
  • Coverage: All target platforms and feature combinations
  • Command: cargo hack clippy --target ${{ matrix.targets }} --each-feature -- -D warnings

Build Validation

  • Tool: cargo build via cargo-hack
  • Coverage: All target platforms and feature combinations
  • Command: cargo hack build --target ${{ matrix.targets }} --each-feature

Sources: .github/workflows/ci.yml(L24 - L28) 

Testing Strategy

The testing approach recognizes the constraints of kernel-space code while maximizing coverage where possible.

Test Execution Matrix

flowchart TD
subgraph subGraph2["Test Execution"]
    TestRun["if: matrix.targets == 'x86_64-unknown-linux-gnu'cargo hack test --target --each-feature -- --nocapture"]
    BuildOnly["Build-only validationfor bare metal targets"]
end
subgraph subGraph1["Test Types"]
    UnitTests["Unit Testscargo hack test"]
    BuildTests["Build Testscargo hack build"]
    FeatureTests["Feature Tests--each-feature"]
end
subgraph subGraph0["Test Targets"]
    LinuxTarget["x86_64-unknown-linux-gnu"]
    BareMetalTargets["Bare metal targetsx86_64-unknown-noneriscv64gc-unknown-none-elfaarch64-unknown-none-softfloat"]
end

BareMetalTargets --> BuildOnly
BareMetalTargets --> BuildTests
BareMetalTargets --> FeatureTests
FeatureTests --> TestRun
LinuxTarget --> BuildTests
LinuxTarget --> FeatureTests
LinuxTarget --> TestRun
LinuxTarget --> UnitTests
UnitTests --> TestRun

Unit Test Execution

  • Platform Restriction: Tests only run on x86_64-unknown-linux-gnu
  • Rationale: Bare metal targets cannot execute standard Rust test framework
  • Configuration: Tests run with --nocapture for full output visibility
  • Feature Coverage: All feature combinations tested via --each-feature

Build-Only Testing

For bare metal targets (x86_64-unknown-none, riscv64gc-unknown-none-elf, aarch64-unknown-none-softfloat), the pipeline performs build-only validation to ensure:

  • Code compiles successfully for target architecture
  • Feature flags work correctly in no-std environments
  • Cross-compilation succeeds without runtime dependencies

Sources: .github/workflows/ci.yml(L30 - L31) 

Documentation Pipeline

The documentation system automatically builds and deploys API documentation to GitHub Pages, ensuring developers always have access to current documentation.

Documentation Workflow

flowchart TD
subgraph Deployment["Deployment"]
    BranchCheck["if: github.ref == env.default-branch"]
    GHPages["JamesIves/github-pages-deploy-action@v4branch: gh-pagesfolder: target/docsingle-commit: true"]
end
subgraph subGraph1["Build Process"]
    DocBuild["cargo doc --no-deps --all-features"]
    IndexGen["Generate redirect index.html$(cargo tree | head -1 | cut -d' ' -f1)"]
    ContinueOnError["continue-on-error: conditionalBased on branch and event type"]
end
subgraph subGraph0["Documentation Job"]
    DocTrigger["Push to default branchOR pull request"]
    DocPerms["permissions:contents: write"]
    DocEnv["RUSTDOCFLAGS:-D rustdoc::broken_intra_doc_links-D missing-docs"]
end

BranchCheck --> GHPages
ContinueOnError --> BranchCheck
DocBuild --> IndexGen
DocEnv --> DocBuild
DocPerms --> DocEnv
DocTrigger --> DocPerms
IndexGen --> ContinueOnError

Documentation Quality Enforcement

The documentation build process enforces strict quality standards:

SettingPurpose
-D rustdoc::broken_intra_doc_linksFails build on broken internal documentation links
-D missing-docsRequires documentation for all public items
--no-depsBuilds only crate documentation, not dependencies
--all-featuresDocuments all feature-gated functionality

Deployment Strategy

  • Target Branch: gh-pages
  • Deployment Condition: Only on pushes to the default branch
  • Commit Strategy: single-commit: true keeps deployment history clean
  • Index Generation: Automatically creates redirect to main crate documentation

Sources: .github/workflows/ci.yml(L33 - L57) 

Pipeline Robustness Features

The CI configuration includes several features designed to maintain pipeline reliability and provide useful feedback:

Error Handling

  • Fail-fast disabled: fail-fast: false allows all matrix jobs to complete even if some fail
  • Conditional error handling: Documentation builds continue on error for non-default branches
  • Warning promotion: Clippy warnings treated as errors to maintain code quality

Toolchain Management

  • Nightly Rust: Uses bleeding-edge features required for no-std development
  • Component installation: Automatically installs required components (rust-src, clippy, rustfmt)
  • Version verification: Explicit Rust version checking for debugging

Resource Optimization

  • Single commit deployment: Minimizes repository size growth from documentation updates
  • Targeted testing: Unit tests only run where feasible (Linux target)
  • Efficient caching: Standard GitHub Actions caching for Rust toolchain and dependencies

Sources: .github/workflows/ci.yml(L9)  .github/workflows/ci.yml(L41)  .github/workflows/ci.yml(L46)