diff --git a/.github/workflows/update_test_coverage.yml b/.github/workflows/update_test_coverage.yml new file mode 100644 index 00000000..ed1941b7 --- /dev/null +++ b/.github/workflows/update_test_coverage.yml @@ -0,0 +1,65 @@ +name: Update TEST_COVERAGE.md + +on: + push: + branches: + - main + workflow_dispatch: + +# Prevent concurrent runs from conflicting commits +concurrency: + group: update-test-coverage + cancel-in-progress: true + +permissions: + contents: write + +jobs: + update-coverage-doc: + name: Update test coverage documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GH_PAT }} + submodules: "true" + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: "1.23.x" + + - uses: actions/cache@v4 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Install Flow CLI + env: + FLOW_CLI_VERSION: v2.7.2 + run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" + + - name: Update PATH + run: | + echo "/root/.local/bin" >> $GITHUB_PATH + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Install dependencies + run: flow deps install --skip-alias --skip-deployments + + - name: Run tests and update TEST_COVERAGE.md + run: ./scripts/update-test-coverage-doc.sh + + - name: Commit and push if changed + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add cadence/tests/TEST_COVERAGE.md + if git diff --cached --quiet; then + echo "No changes to TEST_COVERAGE.md" + else + git commit -m "docs: auto-update TEST_COVERAGE.md with latest test results" + git push + fi diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..b7a820e1 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +.PHONY: lint +lint: + @output=$$(flow cadence lint $$(find cadence -name "*.cdc") 2>&1); \ + echo "$$output"; \ + if echo "$$output" | grep -qE "[1-9][0-9]* problems"; then \ + echo "Lint failed: problems found"; \ + exit 1; \ + fi diff --git a/cadence/tests/TEST_COVERAGE.md b/cadence/tests/TEST_COVERAGE.md index 85db3cf4..7f63f7f7 100644 --- a/cadence/tests/TEST_COVERAGE.md +++ b/cadence/tests/TEST_COVERAGE.md @@ -1,10 +1,22 @@ # Test Coverage Analysis - TidalProtocol (FlowCreditMarket) -**Analysis Date:** 2026-01-28 + + + +| Metric | Value | +|--------|-------| +| **Last Updated** | 2026-01-28 | +| **Coverage** | 89.7% | +| **Test Files** | 31 | +| **Total Tests** | 22 | +| **Passed** | 22 | +| **Failed** | 0 | +| **Status** | All tests passing | + + + **Repository:** TidalProtocol **Core Contract:** FlowCreditMarket.cdc -**Test Coverage:** 89.7% -**Total Core Tests:** 31 test files --- @@ -53,6 +65,15 @@ The protocol uses Cadence's native Test framework with: - Time manipulation capabilities (`Test.moveTime()`, `Test.moveToBlockHeight()`) - Custom test runner script (`run_tests.sh`) to handle contract persistence issues + + + +### Latest Test Results by File + +*Results will be populated automatically after the next PR merge to main.* + + + --- ## Test Organization and Structure @@ -1129,6 +1150,7 @@ Implementing these test enhancements will increase confidence in the protocol's --- -**Document Version:** 1.0 -**Last Updated:** 2026-01-28 +**Document Version:** 1.1 +**Last Updated:** 2026-02-06 +**Auto-updated by:** `.github/workflows/update_test_coverage.yml` on every PR merge to main **Next Review:** After implementation of high-priority test gaps diff --git a/scripts/update-test-coverage-doc.sh b/scripts/update-test-coverage-doc.sh new file mode 100755 index 00000000..81420d33 --- /dev/null +++ b/scripts/update-test-coverage-doc.sh @@ -0,0 +1,174 @@ +#!/usr/bin/env bash +set -euo pipefail + +# update-test-coverage-doc.sh +# +# Runs the Cadence test suite with coverage, parses the output, and updates +# the auto-generated sections of cadence/tests/TEST_COVERAGE.md. +# +# Usage: +# ./scripts/update-test-coverage-doc.sh # run tests and update doc +# ./scripts/update-test-coverage-doc.sh --from-file output.txt # parse existing output + +ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" +DOC_FILE="$ROOT_DIR/cadence/tests/TEST_COVERAGE.md" +TEST_DIR="$ROOT_DIR/cadence/tests" +OUTPUT_FILE="" + +# --------------------------------------------------------------------------- +# Parse arguments +# --------------------------------------------------------------------------- +while [[ $# -gt 0 ]]; do + case "$1" in + --from-file) + OUTPUT_FILE="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac +done + +# --------------------------------------------------------------------------- +# Run tests (or read prior output) +# --------------------------------------------------------------------------- +if [[ -n "$OUTPUT_FILE" ]]; then + echo "Reading test output from $OUTPUT_FILE" + TEST_OUTPUT="$(cat "$OUTPUT_FILE")" +else + echo "Running tests with coverage..." + TEST_OUTPUT="$(flow test --cover --covercode="contracts" \ + "$TEST_DIR"/*_test.cdc 2>&1)" || true +fi + +# --------------------------------------------------------------------------- +# Parse results +# --------------------------------------------------------------------------- +TODAY="$(date -u +%Y-%m-%d)" + +# Coverage percentage — look for "Coverage: XX.X% of statements" +COVERAGE="$(echo "$TEST_OUTPUT" | grep -oP 'Coverage:\s+\K[0-9]+(\.[0-9]+)?%' | head -1)" || true +if [[ -z "$COVERAGE" ]]; then + COVERAGE="N/A" +fi + +# Count test files +TOTAL_FILES="$(find "$TEST_DIR" -maxdepth 1 -name '*_test.cdc' | wc -l)" + +# Individual test results — lines like "- PASS: funcName" or "- FAIL: funcName" +PASS_COUNT="$(echo "$TEST_OUTPUT" | grep -cP '^\s*-\s+PASS:' || true)" +FAIL_COUNT="$(echo "$TEST_OUTPUT" | grep -cP '^\s*-\s+FAIL:' || true)" +TOTAL_TESTS=$((PASS_COUNT + FAIL_COUNT)) + +if [[ "$FAIL_COUNT" -eq 0 && "$TOTAL_TESTS" -gt 0 ]]; then + STATUS="All tests passing" +elif [[ "$TOTAL_TESTS" -eq 0 ]]; then + STATUS="No test results parsed" +else + STATUS="$FAIL_COUNT failing" +fi + +# --------------------------------------------------------------------------- +# Build per-file results table +# --------------------------------------------------------------------------- +# Parse "Test results: " blocks followed by PASS/FAIL lines. +FILE_TABLE="" +CURRENT_FILE="" +FILE_PASS=0 +FILE_FAIL=0 + +flush_file() { + if [[ -n "$CURRENT_FILE" ]]; then + local ftotal=$((FILE_PASS + FILE_FAIL)) + local fstatus="PASS" + if [[ "$FILE_FAIL" -gt 0 ]]; then + fstatus="FAIL" + fi + FILE_TABLE+="| ${CURRENT_FILE} | ${ftotal} | ${FILE_PASS} | ${FILE_FAIL} | ${fstatus} |"$'\n' + fi +} + +while IFS= read -r line; do + if echo "$line" | grep -qP '^Test results:'; then + flush_file + # Extract just the filename + CURRENT_FILE="$(echo "$line" | grep -oP '[^/]+_test\.cdc' || echo "$line")" + FILE_PASS=0 + FILE_FAIL=0 + elif echo "$line" | grep -qP '^\s*-\s+PASS:'; then + FILE_PASS=$((FILE_PASS + 1)) + elif echo "$line" | grep -qP '^\s*-\s+FAIL:'; then + FILE_FAIL=$((FILE_FAIL + 1)) + fi +done <<< "$TEST_OUTPUT" +flush_file + +# --------------------------------------------------------------------------- +# Build the replacement block +# --------------------------------------------------------------------------- +STATS_BLOCK=" + + +| Metric | Value | +|--------|-------| +| **Last Updated** | ${TODAY} | +| **Coverage** | ${COVERAGE} | +| **Test Files** | ${TOTAL_FILES} | +| **Total Tests** | ${TOTAL_TESTS} | +| **Passed** | ${PASS_COUNT} | +| **Failed** | ${FAIL_COUNT} | +| **Status** | ${STATUS} | + +" + +RESULTS_BLOCK=" + + +### Latest Test Results by File + +| File | Tests | Passed | Failed | Status | +|------|-------|--------|--------|--------| +${FILE_TABLE} +" + +# --------------------------------------------------------------------------- +# Update the markdown file +# --------------------------------------------------------------------------- +if [[ ! -f "$DOC_FILE" ]]; then + echo "Error: $DOC_FILE not found" >&2 + exit 1 +fi + +# Replace content between markers using awk +update_section() { + local start_marker="$1" + local end_marker="$2" + local new_content="$3" + local file="$4" + + awk -v start="$start_marker" -v end="$end_marker" -v content="$new_content" ' + $0 ~ start { print content; skip=1; next } + $0 ~ end { skip=0; next } + !skip { print } + ' "$file" +} + +# Apply stats section +TEMP_FILE="$(mktemp)" +update_section "AUTO-GENERATED-STATS-START" "AUTO-GENERATED-STATS-END" \ + "$STATS_BLOCK" "$DOC_FILE" > "$TEMP_FILE" + +# Apply results section +update_section "AUTO-GENERATED-RESULTS-START" "AUTO-GENERATED-RESULTS-END" \ + "$RESULTS_BLOCK" "$TEMP_FILE" > "$DOC_FILE" + +rm -f "$TEMP_FILE" + +echo "" +echo "Updated $DOC_FILE" +echo " Coverage: $COVERAGE" +echo " Tests: $TOTAL_TESTS ($PASS_COUNT passed, $FAIL_COUNT failed)" +echo " Test files: $TOTAL_FILES" +echo " Status: $STATUS"