#!/usr/bin/env bash # e2e_test.sh — the metta use case, end to end against b3u.dev. # # Source: authored in b3u_use_cases (the benchmarking article's # section 2 flow, made executable). # # Drives the whole sequence with your own account: upload metta.sgr, # compile it on the service, download the two deliverable zips, lay # out ~/ccsUseCases/metta exactly as the article shows, and verify # the delivered members. Companion: the metta_bench use case # continues from this layout to a built scb_counts. # # Environment: # B3U_BASE service base URL (required), # e.g. https://b3u.dev # B3U_EMAIL, B3U_PASSWORD your account credentials (required) # B3U_DOWNLOADS download landing dir (default ~/Downloads) # CCSUSECASES_ROOT working root (default ~/ccsUseCases) # CF_ACCESS_CLIENT_ID/-_SECRET optional access-gateway service # token headers, if your deployment sits # behind one # # Exit 0 iff every leg passes. Nothing here stores your password # beyond the login call; the bearer token lives only in this process. set -u : "${B3U_BASE:?set B3U_BASE (e.g. https://b3u.dev)}" : "${B3U_EMAIL:?set B3U_EMAIL}" : "${B3U_PASSWORD:?set B3U_PASSWORD}" DOWNLOADS="${B3U_DOWNLOADS:-$HOME/Downloads}" ROOT_DIR="${CCSUSECASES_ROOT:-$HOME/ccsUseCases}" GRAMMAR="$(cd "$(dirname "$0")" && pwd)/metta.sgr" CURL=(curl -s) if [ -n "${CF_ACCESS_CLIENT_ID:-}" ]; then CURL+=(-H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" -H "CF-Access-Client-Secret: ${CF_ACCESS_CLIENT_SECRET:?}") fi fails=0 pass() { echo " PASS $1"; } fail() { echo " FAIL $1"; fails=$((fails+1)); } [ -f "$GRAMMAR" ] || { echo "FAIL: metta.sgr not found beside this script"; exit 2; } mkdir -p "$DOWNLOADS" echo "== 1. login ==" WALL_ALTERNATIVES=" Compile the grammar with a local cppcc if you have one licensed -- this archive ships the .sgr, which is the artifact the service would compile for you." # ⚠ THE LOGIN MUST DIAGNOSE, NOT TRACEBACK. This piped curl straight # into json.load, so ANY non-JSON reply -- a Cloudflare Access redirect, # a 502, a captive portal -- surfaced as a raw Python JSONDecodeError # followed by "check B3U_EMAIL/B3U_PASSWORD", which was both wrong and # unactionable. Found by a user whose credentials were perfectly fine # and who was told to check them anyway. _lb=$(mktemp); _lh=$(mktemp) code=$("${CURL[@]}" -o "$_lb" -D "$_lh" -w '%{http_code}' \ -X POST "$B3U_BASE/login" -H 'Content-Type: application/json' \ -d "{\"email\":\"$B3U_EMAIL\",\"password\":\"$B3U_PASSWORD\"}") token=$(python3 -c 'import json,sys try: print(json.load(open(sys.argv[1])).get("session_token","")) except Exception: print("")' "$_lb") if [ -n "$token" ]; then pass "login -> bearer token" else if grep -qi 'cloudflareaccess\.com' "$_lh" "$_lb" 2>/dev/null; then fail "login -- $B3U_BASE is behind a Cloudflare Access wall (HTTP $code)" echo " The wall answers BEFORE the application does, so no" echo " email or password can reach it. Your credentials are" echo " not the problem." echo echo " b3u.dev itself is open -- so a wall in front of it means" echo " B3U_BASE is pointed at a PRIVATE host (a staging or" echo " preview hostname), not at the public service. Check" echo " B3U_BASE; it should be https://b3u.dev." if [ -n "${WALL_ALTERNATIVES:-}" ]; then echo "$WALL_ALTERNATIVES" fi # (CF_ACCESS_CLIENT_ID / CF_ACCESS_CLIENT_SECRET are honoured above # if you hold a service token for a private host. Reaching the # public service needs no token.) elif [ "$code" = 401 ] || [ "$code" = 403 ]; then fail "login -- rejected (HTTP $code). Check B3U_EMAIL / B3U_PASSWORD." elif [ "$code" = 000 ]; then fail "login -- could not reach $B3U_BASE at all (DNS, TLS or network)." else fail "login -- no session_token in the reply (HTTP $code)" echo " first bytes: $(head -c 160 "$_lb" | tr -d '\r\n')" fi rm -f "$_lb" "$_lh"; exit 1 fi rm -f "$_lb" "$_lh" AUTH=(-H "Authorization: Bearer $token") echo "== 2. compile metta.sgr on the service (unit: metta) ==" code=$("${CURL[@]}" "${AUTH[@]}" -o "$DOWNLOADS/metta-bundles.zip" \ -w '%{http_code}' -F "file=@$GRAMMAR" \ "$B3U_BASE/units/metta/generate?tokenizer=metta") [ "$code" = 200 ] && pass "POST /units/metta/generate -> bundles zip" \ || { fail "generate (got $code)"; exit 1; } echo "== 3. download the compiled frontend ==" code=$("${CURL[@]}" "${AUTH[@]}" \ -o "$DOWNLOADS/metta-frontend-linux-x86_64.zip" \ -w '%{http_code}' "$B3U_BASE/units/metta/frontend") [ "$code" = 200 ] && pass "GET /units/metta/frontend -> frontend zip" \ || { fail "frontend download (got $code)"; exit 1; } echo "== 4. lay out the working directory (the article's section 2) ==" mkdir -p "$ROOT_DIR/metta" cd "$ROOT_DIR/metta" mv "$DOWNLOADS/metta-bundles.zip" . mv "$DOWNLOADS/metta-frontend-linux-x86_64.zip" . unzip -o -q metta-bundles.zip \ && unzip -o -q metta-frontend-linux-x86_64.zip \ && pass "both zips unpacked in $ROOT_DIR/metta" \ || { fail "unzip"; exit 1; } echo "== 5. verify the delivered layout ==" scbn=$(unzip -l metta-bundles.zip | grep -c " scbcpp/") [ "$scbn" = 10 ] && [ -f scbcpp/lib/libscbcpp.a ] \ && pass "SCB C++ library delivered (10 scbcpp members incl. the lib)" \ || fail "scbcpp members: $scbn" [ -f cpp/mettaKeyWordDefinition.h ] \ && pass "cpp bundle carries mettaKeyWordDefinition.h" \ || fail "mettaKeyWordDefinition.h missing" [ -x ccsmetta ] \ && pass "ccsmetta frontend is executable" \ || fail "ccsmetta missing or not executable" [ -s metta.sgr.fgr ] && [ -s metta.sgr.bfgr ] \ && pass "grammar binaries present (metta.sgr.fgr / .bfgr)" \ || fail "grammar binaries" for f in MANIFEST.json NOTICE.txt README.md PROVENANCE.txt; do [ -f "$f" ] || fail "frontend member missing: $f" done [ "$fails" -eq 0 ] && pass "frontend documentation members present" echo "== 6. parse a real .metta source (and prove it was not truncated) ==" # ⚠ This leg exists because the layout check above passes whether or # not the frontend can actually read MeTTa. Omitting -lt EXITS 0 and # still writes a .bfgr — it just contains almost nothing. A silently # truncated parse looks exactly like a successful one, so the assertion # is on the LISTING LINE COUNT, not on the exit status. cat > e2e_sample.metta <<'SAMPLE' ; e2e sample (= (greet $who) (say "hello" $who)) (= (add $a $b) (+ $a $b)) (greet &self) (add 1 2) (: greet (-> Symbol Expression)) SAMPLE src_lines=$(grep -c '' e2e_sample.metta) ./ccsmetta -lt e2e_sample.metta > /dev/null 2>&1 if [ -f e2e_sample.metta.bfgr ] && [ -f e2e_sample.metta.lis ]; then lis_lines=$(grep -cE '^ +[0-9]+' e2e_sample.metta.lis) if [ "$lis_lines" = "$src_lines" ]; then pass "frontend read all $src_lines source lines (no silent truncation)" else fail "TRUNCATED PARSE: listing has $lis_lines of $src_lines lines — is -lt set?" fi size=$(wc -c < e2e_sample.metta.bfgr) [ "$size" -gt 500 ] \ && pass "wrote a plausibly-sized .bfgr ($size bytes)" \ || fail ".bfgr is only $size bytes — a truncated parse writes ~224" else fail "frontend produced no .bfgr/.lis" fi grep -q '\$who' e2e_sample.metta.urt 2>/dev/null \ && grep -q '&self' e2e_sample.metta.urt \ && pass "decompilation shows \$variables and &space-refs intact" \ || fail "MeTTa token classes missing from the decompilation" echo if [ "$fails" -eq 0 ]; then echo "CCS_MeTTa E2E: ALL PASS ($ROOT_DIR/metta is ready;" echo " continue with the metta_bench use case)" exit 0 else echo "CCS_MeTTa E2E: $fails FAILURE(S)" exit 1 fi