fix: enhance error handling and validation in test coverage scripts
This commit is contained in:
@@ -37,25 +37,68 @@ fi
|
||||
# Extract and print total coverage summary using python
|
||||
LINES_PERCENT=$(python3 - <<'PY'
|
||||
import json
|
||||
summary = json.load(open('coverage/coverage-summary.json'))['total']
|
||||
import sys
|
||||
|
||||
try:
|
||||
with open('coverage/coverage-summary.json') as f:
|
||||
summary = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: Invalid JSON in coverage-summary.json: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except KeyError as e:
|
||||
print(f"Error: Missing key in coverage-summary.json: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Validate structure
|
||||
if 'total' not in summary:
|
||||
print("Error: 'total' key not found in coverage-summary.json", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
total = summary['total']
|
||||
metrics = ['statements', 'branches', 'functions', 'lines']
|
||||
for metric in metrics:
|
||||
if metric not in total:
|
||||
print(f"Error: '{metric}' metric missing from coverage summary", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if not isinstance(total[metric], dict) or 'pct' not in total[metric]:
|
||||
print(f"Error: '{metric}' metric missing 'pct' field", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def fmt(metric):
|
||||
return f"{metric['pct']}% ({metric['covered']}/{metric['total']})"
|
||||
|
||||
print("Frontend coverage summary:")
|
||||
print(f" Statements: {fmt(summary['statements'])}")
|
||||
print(f" Branches: {fmt(summary['branches'])}")
|
||||
print(f" Functions: {fmt(summary['functions'])}")
|
||||
print(f" Lines: {fmt(summary['lines'])}")
|
||||
print(f" Statements: {fmt(total['statements'])}")
|
||||
print(f" Branches: {fmt(total['branches'])}")
|
||||
print(f" Functions: {fmt(total['functions'])}")
|
||||
print(f" Lines: {fmt(total['lines'])}")
|
||||
|
||||
print(summary['lines']['pct'])
|
||||
lines_pct = total['lines']['pct']
|
||||
|
||||
# Validate that lines pct is numeric
|
||||
if not isinstance(lines_pct, (int, float)):
|
||||
print(f"Error: Coverage percentage is not numeric: {lines_pct} ({type(lines_pct).__name__})", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Print just the numeric value
|
||||
print(lines_pct)
|
||||
PY
|
||||
)
|
||||
|
||||
python3 - <<PY
|
||||
import sys
|
||||
from decimal import Decimal
|
||||
from decimal import Decimal, InvalidOperation
|
||||
|
||||
if not '$LINES_PERCENT':
|
||||
print("Error: Failed to extract coverage percentage from test output", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
total = Decimal('$LINES_PERCENT')
|
||||
except InvalidOperation as e:
|
||||
print(f"Error: Coverage value is not numeric: '$LINES_PERCENT' ({e})", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
total = Decimal('$LINES_PERCENT')
|
||||
minimum = Decimal('$MIN_COVERAGE')
|
||||
status = "PASS" if total >= minimum else "FAIL"
|
||||
print(f"Coverage gate: {status} (lines {total}% vs minimum {minimum}%)")
|
||||
|
||||
@@ -101,10 +101,46 @@ COVERAGE_OUTPUT=$(timeout 180 go tool cover -func="$COVERAGE_FILE" 2>&1) || {
|
||||
|
||||
# Extract and display the summary line (total coverage)
|
||||
TOTAL_LINE=$(echo "$COVERAGE_OUTPUT" | awk '/^total:/ {line=$0} END {print line}')
|
||||
|
||||
if [ -z "$TOTAL_LINE" ]; then
|
||||
echo "Error: Coverage report missing 'total:' line"
|
||||
echo "Coverage output:"
|
||||
echo "$COVERAGE_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$TOTAL_LINE"
|
||||
|
||||
# Extract total coverage percentage
|
||||
TOTAL_PERCENT=$(echo "$TOTAL_LINE" | awk '{print substr($3, 1, length($3)-1)}')
|
||||
# Extract total coverage percentage (format: "total: (statements)% (branches)% (functions)% (lines)% XX.X%")
|
||||
# Field $3 is the third space-separated token (line count %)
|
||||
# We need to remove trailing '%' character
|
||||
TOTAL_PERCENT=$(echo "$TOTAL_LINE" | awk '{
|
||||
if (NF < 3) {
|
||||
print "ERROR: Invalid coverage line format" > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
# Extract last field and remove trailing %
|
||||
last_field = $NF
|
||||
if (last_field !~ /^[0-9]+(\.[0-9]+)?%$/) {
|
||||
printf "ERROR: Last field is not a valid percentage: %s\n", last_field > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
# Remove trailing %
|
||||
gsub(/%$/, "", last_field)
|
||||
print last_field
|
||||
}')
|
||||
|
||||
if [ -z "$TOTAL_PERCENT" ] || [ "$TOTAL_PERCENT" = "ERROR" ]; then
|
||||
echo "Error: Could not extract coverage percentage from: $TOTAL_LINE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate that extracted value is numeric (allows decimals and integers)
|
||||
if ! echo "$TOTAL_PERCENT" | grep -qE '^[0-9]+(\.[0-9]+)?$'; then
|
||||
echo "Error: Extracted coverage value is not numeric: '$TOTAL_PERCENT'"
|
||||
echo "Source line: $TOTAL_LINE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Computed coverage: ${TOTAL_PERCENT}% (minimum required ${MIN_COVERAGE}%)"
|
||||
|
||||
@@ -112,11 +148,28 @@ export TOTAL_PERCENT
|
||||
export MIN_COVERAGE
|
||||
|
||||
python3 - <<'PY'
|
||||
import os, sys
|
||||
from decimal import Decimal
|
||||
import os
|
||||
import sys
|
||||
from decimal import Decimal, InvalidOperation
|
||||
|
||||
try:
|
||||
total = Decimal(os.environ['TOTAL_PERCENT'])
|
||||
except InvalidOperation as e:
|
||||
print(f"Error: TOTAL_PERCENT is not numeric: '{os.environ['TOTAL_PERCENT']}' ({e})", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except KeyError:
|
||||
print("Error: TOTAL_PERCENT environment variable not set", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
minimum = Decimal(os.environ['MIN_COVERAGE'])
|
||||
except InvalidOperation as e:
|
||||
print(f"Error: MIN_COVERAGE is not numeric: '{os.environ['MIN_COVERAGE']}' ({e})", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except KeyError:
|
||||
print("Error: MIN_COVERAGE environment variable not set", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
total = Decimal(os.environ['TOTAL_PERCENT'])
|
||||
minimum = Decimal(os.environ['MIN_COVERAGE'])
|
||||
if total < minimum:
|
||||
print(f"Coverage {total}% is below required {minimum}% (set CHARON_MIN_COVERAGE or CPM_MIN_COVERAGE to override)", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
Reference in New Issue
Block a user