71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Verdict test for ledger-coinmarket-10 (extract lane).
|
|
|
|
Exit code 0 = artifact correct; nonzero = artifact wrong.
|
|
Checks: file presence, CSV parse, row count, header contract, rank/order,
|
|
numeric fields, and source payload inclusion. No network access required.
|
|
"""
|
|
import csv, json, os, sys
|
|
|
|
BASE = os.path.dirname(os.path.abspath(__file__))
|
|
MD = os.path.join(BASE, "top-cryptocurrencies.md")
|
|
CSV = os.path.join(BASE, "top-cryptocurrencies.csv")
|
|
SRC = os.path.join(BASE, "source/coins_raw.json")
|
|
|
|
FAIL = []
|
|
def check(name, cond):
|
|
print(("PASS" if cond else "FAIL"), "-", name)
|
|
if not cond: FAIL.append(name)
|
|
|
|
# 1. presence
|
|
check("md exists", os.path.isfile(MD))
|
|
check("csv exists", os.path.isfile(CSV))
|
|
check("source json exists", os.path.isfile(SRC))
|
|
|
|
import re
|
|
# 2. markdown table renders a header + separator + 10 data rows
|
|
md = open(MD).read() if os.path.isfile(MD) else ""
|
|
check("md has header", "| Rank |" in md and "| --- |" in md)
|
|
data_rows = [l for l in md.splitlines() if re.match(r"^\|\s*\d+\s*\|", l)]
|
|
check("md data row count == 10", len(data_rows) == 10)
|
|
|
|
# 3. csv parse + contract
|
|
rows = []
|
|
if os.path.isfile(CSV):
|
|
with open(CSV, newline="") as f:
|
|
rdr = csv.DictReader(f)
|
|
check("csv header == expected", bool(rdr.fieldnames))
|
|
rows = list(rdr)
|
|
check("csv row count == 10", len(rows) == 10)
|
|
check("csv header is 22 cols", bool(rdr.fieldnames) and len(rdr.fieldnames) == 22)
|
|
|
|
def is_num(s):
|
|
try:
|
|
float(s); return True
|
|
except (TypeError, ValueError):
|
|
return False
|
|
|
|
bad = 0
|
|
for r in rows:
|
|
if not (is_num(r["rank"]) and int(r["rank"]) == int(rows.index(r) + 1)):
|
|
bad += 1
|
|
for k in ("price_usd","market_cap_usd","total_volume_usd","circulating_supply"):
|
|
if not is_num(r[k]): bad += 1
|
|
check("csv ranks == 1..10 & numeric fields parse", bad == 0)
|
|
|
|
# 4. order: market cap non-increasing across rows
|
|
caps = [float(r["market_cap_usd"]) for r in rows]
|
|
check("market cap non-increasing (desc)", all(caps[i] >= caps[i+1] for i in range(len(caps)-1)))
|
|
|
|
# 5. source payload included (never fabricated)
|
|
try:
|
|
snap = json.load(open(SRC))
|
|
check("source json has 10 rows", isinstance(snap, dict) and len(snap.get("rows", [])) == 10)
|
|
check("source json fetched_at set", bool(snap.get("fetched_at")))
|
|
except Exception as e:
|
|
check("source json loads", False)
|
|
|
|
print()
|
|
print("RESULT:", "OK" if not FAIL else f"{len(FAIL)} FAILURES: {FAIL}")
|
|
sys.exit(1 if FAIL else 0)
|