Files
ginxsom/tests/nip94_test_bud08.sh
2025-09-10 13:15:18 -04:00

240 lines
8.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# BUD-08 NIP-94 File Metadata Tags Test Suite
# This test is created FIRST (TDD) and will FAIL until implementation is added to src/main.c.
#
# Expected procedures to be implemented in src/main.c (BUD-08 section):
# - nip94_is_enabled() -> Read server_config.nip94_enabled (default true)
# - nip94_get_origin() -> Read server_config.cdn_origin (default http://localhost:9001)
# - mime_to_extension() -> Centralize MIME to extension mapping
# - nip94_build_blob_url() -> Build canonical blob URL from origin + sha256 + extension
# - get_file_dimensions() -> Detect WxH for PNG, JPEG, WebP (parse headers only)
# - nip94_build_tags() -> Build tags: ["url",...], ["m",...], ["x",...], ["size",...], optional ["dim","WxH"]
# - nip94_attach_to_descriptor() -> Attach nip94 array to JSON response in /upload and /mirror
#
# Integration points expected:
# - PUT /upload success JSON includes "nip94" array
# - PUT /mirror success JSON includes "nip94" array
#
# Requirements:
# - curl, jq, sqlite3 must be available
# - Server should be running at http://localhost:9001 (restart-all.sh)
set -e
SERVER_URL="http://localhost:9001"
UPLOAD_ENDPOINT="${SERVER_URL}/upload"
MIRROR_ENDPOINT="${SERVER_URL}/mirror"
DB_PATH="db/ginxsom.db"
echo "=== BUD-08 NIP-94 File Metadata Tags Test Suite ==="
# Prereq checks
if ! command -v curl >/dev/null 2>&1; then
echo "ERROR: curl not found"
exit 1
fi
if ! command -v jq >/dev/null 2>&1; then
echo "ERROR: jq not found (required for JSON parsing)"
exit 1
fi
if ! command -v sqlite3 >/dev/null 2>&1; then
echo "ERROR: sqlite3 not found"
exit 1
fi
# Helpers
die() {
echo "FATAL: $*" 1>&2
exit 1
}
json_has_nip94() {
local json="$1"
echo "$json" | jq -e '.nip94 and ( .nip94 | type == "array" )' >/dev/null 2>&1
}
nip94_get_tag() {
local json="$1"
local key="$2"
echo "$json" | jq -r --arg k "$key" '.nip94 | map(select(.[0]==$k)) | if length>0 then .[0][1] else empty end'
}
# Authentication helper - create Blossom auth header for uploads
create_auth_header() {
local file_path="$1"
local hash=$(sha256sum "$file_path" | awk '{print $1}')
# Create Blossom event (kind 24242) with required tags
local expiration=$(date -d "+3600 seconds" +%s)
local event=$(nak event -k 24242 -c "" \
--tag "t=upload" \
--tag "x=$hash" \
--tag "expiration=$expiration" \
--sec "0000000000000000000000000000000000000000000000000000000000000001")
echo "Nostr $(echo "$event" | base64 -w 0)"
}
# Configuration is stored in database 'config' table with key-value pairs
# Create temporary working directory
WORKDIR="tests/tmp_bud08"
mkdir -p "$WORKDIR"
# Create a tiny 1x1 PNG (base64)
TINY_PNG_B64="iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO0RzjoAAAAASUVORK5CYII="
PNG_FILE="$WORKDIR/one_by_one.png"
echo "$TINY_PNG_B64" | base64 -d > "$PNG_FILE"
# Compute expected values
CONTENT_TYPE="image/png"
FILE_SIZE=$(wc -c < "$PNG_FILE" | tr -d ' ')
SHA256_HEX=$(sha256sum "$PNG_FILE" | awk '{print $1}')
echo ""
echo "Test artifact:"
echo " File: $PNG_FILE"
echo " Size: $FILE_SIZE"
echo " SHA256: $SHA256_HEX"
echo ""
# --- Test 1: PUT /upload returns nip94 with minimal required tags
echo "=== Test 1: PUT /upload returns nip94 minimal tags ==="
AUTH_HEADER=$(create_auth_header "$PNG_FILE")
UPLOAD_JSON=$(curl -s -X PUT "$UPLOAD_ENDPOINT" \
-H "Authorization: $AUTH_HEADER" \
-H "Content-Type: $CONTENT_TYPE" \
--data-binary @"$PNG_FILE")
echo "Upload Response JSON:"
echo "$UPLOAD_JSON" | jq '.' 2>/dev/null || echo "$UPLOAD_JSON"
echo ""
if json_has_nip94 "$UPLOAD_JSON"; then
URL_FIELD=$(echo "$UPLOAD_JSON" | jq -r '.url')
TYPE_FIELD=$(echo "$UPLOAD_JSON" | jq -r '.type')
SIZE_FIELD=$(echo "$UPLOAD_JSON" | jq -r '.size')
SHA256_FIELD=$(echo "$UPLOAD_JSON" | jq -r '.sha256')
TAG_URL=$(nip94_get_tag "$UPLOAD_JSON" "url")
TAG_M=$(nip94_get_tag "$UPLOAD_JSON" "m")
TAG_X=$(nip94_get_tag "$UPLOAD_JSON" "x")
TAG_SIZE=$(nip94_get_tag "$UPLOAD_JSON" "size")
PASS=1
[ -n "$TAG_URL" ] || { echo "FAIL: nip94 missing url tag"; PASS=0; }
[ -n "$TAG_M" ] || { echo "FAIL: nip94 missing m tag"; PASS=0; }
[ -n "$TAG_X" ] || { echo "FAIL: nip94 missing x tag"; PASS=0; }
[ -n "$TAG_SIZE" ] || { echo "FAIL: nip94 missing size tag"; PASS=0; }
# Validate tag values match descriptor
[ "$TAG_URL" = "$URL_FIELD" ] || { echo "FAIL: nip94 url tag != descriptor url"; PASS=0; }
[ "$TAG_M" = "$TYPE_FIELD" ] || { echo "FAIL: nip94 m tag != descriptor type"; PASS=0; }
[ "$TAG_X" = "$SHA256_FIELD" ] || { echo "FAIL: nip94 x tag != descriptor sha256"; PASS=0; }
[ "$TAG_SIZE" = "$SIZE_FIELD" ] || { echo "FAIL: nip94 size tag != descriptor size"; PASS=0; }
if [ "$PASS" = "1" ]; then
echo "✅ Test 1 PASSED: nip94 minimal tags present and correct"
else
echo "❌ Test 1 FAILED"
fi
else
echo "❌ Test 1 FAILED: Response missing nip94 array"
fi
# --- Test 2: dim present and equals 1x1 for PNG
echo ""
echo "=== Test 2: dim tag for 1x1 PNG ==="
echo "Response JSON (same as Test 1):"
echo "$UPLOAD_JSON" | jq '.' 2>/dev/null || echo "$UPLOAD_JSON"
echo ""
TAG_DIM=$(nip94_get_tag "$UPLOAD_JSON" "dim" || true)
if [ -n "$TAG_DIM" ]; then
if [ "$TAG_DIM" = "1x1" ]; then
echo "✅ Test 2 PASSED: dim tag present and equals 1x1"
else
echo "❌ Test 2 FAILED: dim tag expected 1x1, got '$TAG_DIM'"
fi
else
echo "❌ Test 2 FAILED: dim tag not present"
fi
# --- Test 3: Check configuration defaults in config table
echo ""
echo "=== Test 3: Configuration defaults test ==="
echo "Database Configuration JSON:"
CONFIG_JSON=$(sqlite3 "$DB_PATH" "SELECT json_object('key', key, 'value', value) FROM config WHERE key IN ('nip94_enabled', 'cdn_origin') ORDER BY key;" 2>/dev/null | sed 's/^/ /')
if [ -n "$CONFIG_JSON" ]; then
echo "$CONFIG_JSON" | while read line; do echo " $line"; done
else
echo " No NIP-94 config found"
fi
echo ""
echo -n "Test 3 - Configuration defaults: "
if sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM config WHERE key IN ('nip94_enabled', 'cdn_origin');" | grep -q "2"; then
echo "✓ PASS - Configuration defaults found"
else
echo "✗ FAIL - Missing configuration defaults"
echo "Debug: config table contents:"
sqlite3 "$DB_PATH" "SELECT * FROM config;" 2>/dev/null || echo "config table does not exist"
fi
# --- Test 4: Check NIP-94 enabled configuration
echo ""
echo "=== Test 4: NIP-94 enabled check test ==="
echo "NIP-94 Configuration JSON:"
NIP94_CONFIG_JSON=$(sqlite3 "$DB_PATH" "SELECT json_object('nip94_enabled', value) FROM config WHERE key='nip94_enabled';" 2>/dev/null)
if [ -n "$NIP94_CONFIG_JSON" ]; then
echo " $NIP94_CONFIG_JSON"
else
echo " {\"nip94_enabled\": null}"
fi
echo ""
echo -n "Test 4 - NIP-94 enabled check: "
nip94_enabled=$(sqlite3 "$DB_PATH" "SELECT value FROM config WHERE key='nip94_enabled';" 2>/dev/null)
if [[ "$nip94_enabled" == "true" ]]; then
echo "✓ PASS - NIP-94 is enabled"
else
echo "✗ FAIL - NIP-94 not enabled (got: '$nip94_enabled')"
fi
# --- Test 5: PUT /mirror returns nip94 minimal tags (best effort, network dependent)
echo ""
echo "=== Test 5: PUT /mirror returns nip94 minimal tags (network dependent) ==="
# Use a public small PNG; if network/policy blocks, mark INFO instead of failure.
REMOTE_URL="https://upload.wikimedia.org/wikipedia/commons/3/3c/Shaki_waterfall.jpg"
MIRROR_JSON=$(curl -s -X PUT "$MIRROR_ENDPOINT" \
-H "Content-Type: application/json" \
--data "{\"url\":\"$REMOTE_URL\"}")
echo "Mirror Response JSON:"
echo "$MIRROR_JSON" | jq '.' 2>/dev/null || echo "$MIRROR_JSON"
echo ""
HTTP_OK=$(echo "$MIRROR_JSON" | jq -e '.sha256 and .type and .size' >/dev/null 2>&1; echo $?)
if [ "$HTTP_OK" = "0" ]; then
if json_has_nip94 "$MIRROR_JSON"; then
TAG_URL_M=$(nip94_get_tag "$MIRROR_JSON" "url")
TAG_M_M=$(nip94_get_tag "$MIRROR_JSON" "m")
TAG_X_M=$(nip94_get_tag "$MIRROR_JSON" "x")
TAG_SIZE_M=$(nip94_get_tag "$MIRROR_JSON" "size")
if [ -n "$TAG_URL_M" ] && [ -n "$TAG_M_M" ] && [ -n "$TAG_X_M" ] && [ -n "$TAG_SIZE_M" ]; then
echo "✅ Test 5 PASSED: nip94 minimal tags present for mirror"
else
echo "❌ Test 5 FAILED: nip94 minimal tags missing for mirror response"
fi
else
echo "❌ Test 5 FAILED: mirror response missing nip94 array"
fi
else
echo " Test 5 INFO: mirror request did not return a blob descriptor (network or policy); skipping strict check"
fi
# Cleanup
rm -rf "$WORKDIR"
echo ""
echo "=== End of BUD-08 NIP-94 Test Suite ==="