Skip to content
Draft
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
65 changes: 65 additions & 0 deletions .github/workflows/update_test_coverage.yml
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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
32 changes: 27 additions & 5 deletions cadence/tests/TEST_COVERAGE.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
# Test Coverage Analysis - TidalProtocol (FlowCreditMarket)

**Analysis Date:** 2026-01-28
<!-- AUTO-GENERATED-STATS-START -->
<!-- Generated by scripts/update-test-coverage-doc.sh — do not edit manually -->

| Metric | Value |
|--------|-------|
| **Last Updated** | 2026-01-28 |
| **Coverage** | 89.7% |
| **Test Files** | 31 |
| **Total Tests** | 22 |
| **Passed** | 22 |
| **Failed** | 0 |
| **Status** | All tests passing |

<!-- AUTO-GENERATED-STATS-END -->

**Repository:** TidalProtocol
**Core Contract:** FlowCreditMarket.cdc
**Test Coverage:** 89.7%
**Total Core Tests:** 31 test files

---

Expand Down Expand Up @@ -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

<!-- AUTO-GENERATED-RESULTS-START -->
<!-- Generated by scripts/update-test-coverage-doc.sh — do not edit manually -->

### Latest Test Results by File

*Results will be populated automatically after the next PR merge to main.*

<!-- AUTO-GENERATED-RESULTS-END -->

---

## Test Organization and Structure
Expand Down Expand Up @@ -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
174 changes: 174 additions & 0 deletions scripts/update-test-coverage-doc.sh
Original file line number Diff line number Diff line change
@@ -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: <path>" 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="<!-- AUTO-GENERATED-STATS-START -->
<!-- Generated by scripts/update-test-coverage-doc.sh — do not edit manually -->

| Metric | Value |
|--------|-------|
| **Last Updated** | ${TODAY} |
| **Coverage** | ${COVERAGE} |
| **Test Files** | ${TOTAL_FILES} |
| **Total Tests** | ${TOTAL_TESTS} |
| **Passed** | ${PASS_COUNT} |
| **Failed** | ${FAIL_COUNT} |
| **Status** | ${STATUS} |

<!-- AUTO-GENERATED-STATS-END -->"

RESULTS_BLOCK="<!-- AUTO-GENERATED-RESULTS-START -->
<!-- Generated by scripts/update-test-coverage-doc.sh — do not edit manually -->

### Latest Test Results by File

| File | Tests | Passed | Failed | Status |
|------|-------|--------|--------|--------|
${FILE_TABLE}
<!-- AUTO-GENERATED-RESULTS-END -->"

# ---------------------------------------------------------------------------
# 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"
Loading