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
66 changes: 66 additions & 0 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,72 @@ jobs:
- name: Build all crates
run: cargo build --all --verbose

# ─────────────────────────────────────────────
# COVERAGE — code coverage for contract tests
# ─────────────────────────────────────────────
coverage:
name: Coverage Report
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
env:
RUSTUP_TOOLCHAIN: stable
with:
components: llvm-tools-preview
- name: Install grcov
run: cargo install grcov
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
contracts/target
key: ${{ runner.os }}-cargo-coverage-${{ hashFiles('''contracts/Cargo.lock''') }}
restore-keys: |
${{ runner.os }}-cargo-coverage-
${{ runner.os }}-cargo-
- name: Generate coverage data
working-directory: contracts
run: |
export CARGO_INCREMENTAL=0
export RUSTFLAGS="-Cinstrument-coverage"
export RUSTDOCFLAGS="-Cinstrument-coverage"
export LLVM_PROFILE_FILE="target/coverage/cargo-test-%p-%m.profraw"
cargo test --workspace --all-features
- name: Generate coverage report
working-directory: contracts
run: |
grcov target/coverage \
--source-dir . \
--output-type lcov \
--branch \
--ignore-not-existing \
--ignore "/*" \
--ignore "**/tests/*" \
--ignore "**/test.rs" \
--ignore "**/target/**" \
--output-path target/coverage/lcov.info
- name: Upload coverage to artifacts
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: contracts/target/coverage/
- name: Upload to Coveralls (if available)
continue-on-error: true
working-directory: contracts
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
run: |
if [ -n "$COVERALLS_REPO_TOKEN" ]; then
cargo install cargo-coveralls
cargo coveralls --file target/coverage/lcov.info
else
echo "COVERALLS_REPO_TOKEN not set — skipping Coveralls upload."
fi

# ─────────────────────────────────────────────
# BACKEND — NestJS
# ─────────────────────────────────────────────
Expand Down
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ Thumbs.db
.vscode/
.idea/
*.swp
*.swo
*.swo

# Generated script artifacts
scripts/wasm-hashes.json
scripts/sdk-compat-*.md
target/coverage/
62 changes: 62 additions & 0 deletions scripts/coverage.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Code-coverage runner for Oraculum contracts (Windows / PowerShell).
.DESCRIPTION
Generates coverage reports for the Rust contract workspace using
cargo-tarpaulin (preferred) or grcov.
.PARAMETER Engine
Coverage engine to use: "tarpaulin" (default) or "grcov".
.PARAMETER Open
Switch; if set, opens the generated HTML report.
#>

param(
[Parameter(Mandatory = $false)]
[ValidateSet("tarpaulin", "grcov")]
[string]$Engine = "tarpaulin",

[Parameter(Mandatory = $false)]
[switch]$Open = $false
)

$ErrorActionPreference = "Stop"
$WorkspaceDir = Split-Path -Path $PSScriptRoot -Parent
$ReportDir = Join-Path -Path $WorkspaceDir -ChildPath "target/coverage"
New-Item -ItemType Directory -Force -Path $ReportDir | Out-Null

Write-Host "━━━ Oraculum Coverage Report ━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor Cyan
Write-Host " Engine: $Engine"
Write-Host " Contracts: $((Join-Path $WorkspaceDir 'contracts'))"
Write-Host ""

if ($Engine -eq "tarpaulin") {
# Check if tarpaulin is installed
$null = Get-Command cargo-tarpaulin -ErrorAction SilentlyContinue
if (-not $?) {
Write-Error "cargo-tarpaulin not found. Run: cargo install cargo-tarpaulin"
exit 1
}

Push-Location (Join-Path $WorkspaceDir "contracts")
try {
cargo tarpaulin --workspace --all-features --out Html --out Xml --output-dir $ReportDir --skip-clean --verbose
} finally {
Pop-Location
}

Write-Host "✓ Coverage report generated:" -ForegroundColor Green
Write-Host " HTML: $(Join-Path $ReportDir 'tarpaulin-report.html')"
Write-Host " XML: $(Join-Path $ReportDir 'cobertura.xml')"
}
else {
Write-Error "grcov on Windows requires additional setup. Use tarpaulin instead."
exit 1
}

if ($Open) {
$reportFile = Join-Path $ReportDir "tarpaulin-report.html"
if (Test-Path $reportFile) {
Start-Process $reportFile
}
}
126 changes: 126 additions & 0 deletions scripts/coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/env bash
set -euo pipefail

# ────────────────────────────────────────────────────────────────
# scripts/coverage.sh — Code-coverage runner for Oraculum contracts
#
# Prerequisites:
# cargo-tarpaulin (install: cargo install cargo-tarpaulin)
# grcov (install: cargo install grcov)
# llvm-tools-preview (for grcov profiling, install: rustup component add llvm-tools-preview)
#
# Usage:
# ./scripts/coverage.sh # run all contracts with tarpaulin (default)
# ./scripts/coverage.sh --engine grcov # run with grcov instead
# ./scripts/coverage.sh --open # open HTML report after generation
# ────────────────────────────────────────────────────────────────

ENGINE="tarpaulin"
OPEN_REPORT="false"
WORKSPACE_DIR="$(cd "$(dirname "$0")/.." && pwd)"
REPORT_DIR="${WORKSPACE_DIR}/target/coverage"

# ── Parse arguments ────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--engine) ENGINE="$2"; shift 2 ;;
--open) OPEN_REPORT="true"; shift ;;
*) echo "Unknown option: $1"; exit 1 ;;
esac
done

echo "━━━ Oraculum Coverage Report ━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Engine: ${ENGINE}"
echo " Contracts workspace: ${WORKSPACE_DIR}/contracts"
echo ""

mkdir -p "${REPORT_DIR}"

# ── Coverage via cargo-tarpaulin ───────────────────────────────
if [[ "${ENGINE}" == "tarpaulin" ]]; then
if ! command -v cargo-tarpaulin &>/dev/null; then
echo "Error: cargo-tarpaulin not installed."
echo " Run: cargo install cargo-tarpaulin"
exit 1
fi

echo "→ Running cargo-tarpaulin on contract workspace…"
cd "${WORKSPACE_DIR}/contracts"

cargo tarpaulin \
--workspace \
--all-features \
--out Html \
--out Xml \
--output-dir "${REPORT_DIR}" \
--skip-clean \
--verbose

echo ""
echo "✓ Coverage report generated:"
echo " HTML: ${REPORT_DIR}/tarpaulin-report.html"
echo " XML: ${REPORT_DIR}/cobertura.xml"

# ── Coverage via grcov (nightly / llvm-profiling) ─────────────
elif [[ "${ENGINE}" == "grcov" ]]; then
if ! command -v grcov &>/dev/null; then
echo "Error: grcov not installed."
echo " Run: cargo install grcov"
exit 1
fi

echo "→ Running tests with llvm profiling…"
cd "${WORKSPACE_DIR}/contracts"

export CARGO_INCREMENTAL=0
export RUSTFLAGS="-Cinstrument-coverage"
export RUSTDOCFLAGS="-Cinstrument-coverage"
export LLVM_PROFILE_FILE="${REPORT_DIR}/cargo-test-%p-%m.profraw"

# Run tests — output is shown on failure for debugging
TEST_LOG=$(mktemp)
if cargo test --workspace --all-features > "${TEST_LOG}" 2>&1; then
echo " ✓ All tests passed."
else
echo " ⚠ Some tests failed. Coverage report will be incomplete."
echo " Test output (last 20 lines):"
tail -20 "${TEST_LOG}" | sed 's/^/ /'
fi
rm -f "${TEST_LOG}"

echo "→ Generating coverage with grcov…"
grcov "${REPORT_DIR}" \
--source-dir "${WORKSPACE_DIR}/contracts" \
--output-type html \
--branch \
--ignore-not-existing \
--ignore "/*" \
--ignore "**/tests/*" \
--ignore "**/test.rs" \
--ignore "**/target/**" \
--output-path "${REPORT_DIR}/grcov-report"

echo ""
echo "✓ Coverage report generated:"
echo " HTML: ${REPORT_DIR}/grcov-report/index.html"

# Clean up profraw files
rm -f "${REPORT_DIR}"/*.profraw
else
echo "Error: unknown engine '${ENGINE}'. Use 'tarpaulin' or 'grcov'."
exit 1
fi

# ── Optionally open the report ────────────────────────────────
if [[ "${OPEN_REPORT}" == "true" ]]; then
REPORT_FILE="${REPORT_DIR}/tarpaulin-report.html"
[[ "${ENGINE}" == "grcov" ]] && REPORT_FILE="${REPORT_DIR}/grcov-report/index.html"

if command -v xdg-open &>/dev/null; then
xdg-open "${REPORT_FILE}"
elif command -v open &>/dev/null; then
open "${REPORT_FILE}"
else
echo "→ Report available at: ${REPORT_FILE}"
fi
fi
Loading