#!/usr/bin/env bash # Test runner for ugi-cli against cases.json set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" UGI="$SCRIPT_DIR/ugi" if [[ $# -ne 2 ]]; then echo "Usage: $0 " >&2 exit 1 fi REGISTRY="$1" CASES="$2" if [[ ! -f "$REGISTRY" ]]; then echo "error: registry not found: $REGISTRY" >&2; exit 1; fi if [[ ! -f "$CASES" ]]; then echo "error: cases not found: $CASES" >&2; exit 1; fi if [[ ! -x "$UGI" ]]; then echo "error: ugi not found at $UGI" >&2; exit 1; fi export UGI_REGISTRY="$REGISTRY" pass=0 fail=0 skip=0 failures=() # ── Helpers ────────────────────────────────────────────────────────────────── expect_field_label() { local case_id="$1" field_code="$2" jq -r --arg id "$case_id" --arg fc "$field_code" ' .cases[] | select(.id == $id) | .decoded.fields[$fc] //empty | if .type == "direct" then .label elif .type == "special" and .dimensions then [.dimensions | to_entries[] | "\(.key): \(.value.label)"] | join("; ") elif .type == "special" and .domains then [.domains[] | .name + (if .paid then " ($)" else "" end)] | join(", ") elif .entries then [.entries[] | .name + (if .value != null then "=\(.label)" else "" end) + (if .paid then " [$]" else "" end) + (if .aspire then " [+\(.aspire)]" else "" end) ] | join(", ") else empty end ' "$CASES" } run_decode_test() { local case_id="$1" uri="$2" local output output=$("$UGI" decode "$uri" 2>&1) || true local exp_ver exp_ver=$(jq -r --arg id "$case_id" '.cases[] | select(.id == $id) | .decoded.version' "$CASES") if ! echo "$output" | grep -qF "Version: $exp_ver"; then failures+=("$case_id/decode/version: expected '$exp_ver'") return 1 fi local exp_handle exp_handle=$(jq -r --arg id "$case_id" '.cases[] | select(.id == $id) | .decoded.handle' "$CASES") if ! echo "$output" | grep -qF "Handle: @$exp_handle"; then failures+=("$case_id/decode/handle: expected '@$exp_handle'") return 1 fi local field_codes field_codes=$(jq -r --arg id "$case_id" '.cases[] | select(.id == $id) | .decoded.fields | keys[]' "$CASES" 2>/dev/null) || return 0 for fc in $field_codes; do local exp_label exp_label=$(expect_field_label "$case_id" "$fc") [[ -z "$exp_label" ]] && continue local entry_count entry_count=$(jq -r --arg id "$case_id" --arg fc "$fc" ' .cases[] | select(.id == $id) | .decoded.fields[$fc].entries // [] | length ' "$CASES") if [[ "$entry_count" -gt 0 ]]; then local entry_names entry_names=$(jq -r --arg id "$case_id" --arg fc "$fc" ' .cases[] | select(.id == $id) | .decoded.fields[$fc].entries[]? | .name ' "$CASES") for ename in $entry_names; do if ! echo "$output" | grep -qF "$ename"; then failures+=("$case_id/decode/$fc: missing entry name '$ename' in output") return 1 fi done elif [[ -n "$exp_label" ]]; then IFS=';' read -ra label_parts <<< "$exp_label" for lp in "${label_parts[@]}"; do lp="${lp## }" if ! echo "$output" | grep -qF "$lp"; then failures+=("$case_id/decode/$fc: missing '$lp' in output") return 1 fi done fi done return 0 } run_convert_test() { local case_id="$1" uri="$2" expected_block="$3" local block_output block_output=$("$UGI" convert "$uri" 2>&1) || true if ! echo "$block_output" | grep -qF "BEGIN UGI BLOCK"; then failures+=("$case_id/convert-uri2block: missing BEGIN header") return 1 fi if ! echo "$block_output" | grep -qF "END UGI BLOCK"; then failures+=("$case_id/convert-uri2block: missing END footer") return 1 fi local exp_handle exp_handle=$(jq -r --arg id "$case_id" '.cases[] | select(.id == $id) | .decoded.handle' "$CASES") if ! echo "$block_output" | grep -qF "@$exp_handle"; then failures+=("$case_id/convert-uri2block: missing handle '@$exp_handle'") return 1 fi local uri_output uri_output=$("$UGI" convert "$block_output" 2>&1) || true if [[ "${uri_output,,}" != "ugi:"* ]]; then failures+=("$case_id/convert-block2uri: output doesn't start with 'ugi:' got '$uri_output'") return 1 fi if ! echo "$uri_output" | grep -qF "@$exp_handle"; then failures+=("$case_id/convert-block2uri: missing handle in roundtrip") return 1 fi return 0 } # ── Run tests ──────────────────────────────────────────────────────────────── echo "=== UGI CLI Test Suite ===" echo "Registry: $REGISTRY" echo "Cases: $CASES" echo "CLI: $UGI" echo case_ids=$(jq -r '.cases[].id' "$CASES") for cid in $case_ids; do uri=$(jq -r --arg id "$cid" '.cases[] | select(.id == $id) | .uri // empty' "$CASES") has_decoded=$(jq -r --arg id "$cid" '.cases[] | select(.id == $id) | .decoded // empty | if . then "yes" else "no" end' "$CASES") if [[ -z "$uri" ]]; then printf " SKIP %-35s (no single URI)\n" "$cid" skip=$((skip + 1)) continue fi if [[ "$has_decoded" == "no" || -z "$has_decoded" ]]; then printf " SKIP %-35s (no decoded expectations)\n" "$cid" skip=$((skip + 1)) continue fi if run_decode_test "$cid" "$uri"; then printf " PASS %-35s decode\n" "$cid" pass=$((pass + 1)) else printf " FAIL %-35s decode\n" "$cid" fail=$((fail + 1)) fi block=$(jq -r --arg id "$cid" '.cases[] | select(.id == $id) | .block // empty' "$CASES") if [[ -n "$block" ]]; then if run_convert_test "$cid" "$uri" "$block"; then printf " PASS %-35s convert roundtrip\n" "$cid" pass=$((pass + 1)) else printf " FAIL %-35s convert roundtrip\n" "$cid" fail=$((fail + 1)) fi fi done echo echo "=== Results: $pass passed, $fail failed, $skip skipped ===" if [[ ${#failures[@]} -gt 0 ]]; then echo echo "Failures:" for f in "${failures[@]}"; do echo " - $f" done exit 1 fi exit 0