#!/usr/bin/env bash # e2e_test.sh — the ccs_json 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 json.sgr, # compile it on the service, download the two deliverable zips, lay # out ~/ccsUseCases/ccs_json exactly as the article shows, and verify # the delivered members. Companion: the ccs_json_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)/json.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: json.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 json.sgr on the service (unit: json) ==" code=$("${CURL[@]}" "${AUTH[@]}" -o "$DOWNLOADS/ccs_json-bundles.zip" \ -w '%{http_code}' -F "file=@$GRAMMAR" "$B3U_BASE/units/json/generate") [ "$code" = 200 ] && pass "POST /units/json/generate -> bundles zip" \ || { fail "generate (got $code)"; exit 1; } echo "== 3. download the compiled frontend ==" code=$("${CURL[@]}" "${AUTH[@]}" \ -o "$DOWNLOADS/ccs_json-frontend-linux-x86_64.zip" \ -w '%{http_code}' "$B3U_BASE/units/json/frontend") [ "$code" = 200 ] && pass "GET /units/json/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/ccs_json" cd "$ROOT_DIR/ccs_json" mv "$DOWNLOADS/ccs_json-bundles.zip" . mv "$DOWNLOADS/ccs_json-frontend-linux-x86_64.zip" . unzip -o -q ccs_json-bundles.zip \ && unzip -o -q ccs_json-frontend-linux-x86_64.zip \ && pass "both zips unpacked in $ROOT_DIR/ccs_json" \ || { fail "unzip"; exit 1; } echo "== 5. verify the delivered layout ==" scbn=$(unzip -l ccs_json-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/jsonKeyWordDefinition.h ] \ && pass "cpp bundle carries jsonKeyWordDefinition.h" \ || fail "jsonKeyWordDefinition.h missing" [ -x ccsjson ] \ && pass "ccsjson frontend is executable" \ || fail "ccsjson missing or not executable" [ -s json.sgr.fgr ] && [ -s json.sgr.bfgr ] \ && pass "grammar binaries present (json.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 if [ "$fails" -eq 0 ]; then echo "CCS_JSON E2E: ALL PASS ($ROOT_DIR/ccs_json is ready;" echo " continue with the ccs_json_bench use case)" exit 0 else echo "CCS_JSON E2E: $fails FAILURE(S)" exit 1 fi