#!/usr/bin/env bash # tests.sh — mem0server endpoint tests # Usage: bash tests.sh [BASE_URL] # Default base: http://192.168.0.200:8420 BASE="${1:-http://192.168.0.200:8420}" PASS=0 FAIL=0 # Colours GREEN='\033[0;32m' RED='\033[0;31m' CYAN='\033[0;36m' BOLD='\033[1m' RESET='\033[0m' sep() { echo -e "\n${CYAN}${BOLD}━━━ $* ━━━${RESET}"; } ok() { echo -e "${GREEN}✓ $*${RESET}"; ((PASS++)); } fail() { echo -e "${RED}✗ $*${RESET}"; ((FAIL++)); } # Run curl, pretty-print with jq, check HTTP 200 run() { local label="$1"; shift echo -e "\n${BOLD}▶ $label${RESET}" local body body=$(curl -s -w "\n__STATUS__%{http_code}" "$@") local status status=$(echo "$body" | tail -1 | sed 's/__STATUS__//') local json json=$(echo "$body" | sed '$d') echo "$json" | jq . 2>/dev/null || echo "$json" if [[ "$status" == "200" ]]; then ok "HTTP $status" else fail "HTTP $status" fi } # ───────────────────────────────────────────── sep "HEALTH" # ───────────────────────────────────────────── run "GET /health" \ "$BASE/health" # ───────────────────────────────────────────── sep "/memories (conversational — OpenClaw)" # ───────────────────────────────────────────── run "POST /memories — plain text" \ -X POST "$BASE/memories" \ -H "Content-Type: application/json" \ -d '{"text": "I love building AI agents and I prefer Python over JavaScript", "user_id": "testuser"}' run "POST /memories — messages array" \ -X POST "$BASE/memories" \ -H "Content-Type: application/json" \ -d '{ "messages": [{"role": "user", "content": "I have been using Vim for 10 years and hate GUI editors"}], "user_id": "testuser" }' run "POST /memories/search — programming preferences" \ -X POST "$BASE/memories/search" \ -H "Content-Type: application/json" \ -d '{"query": "programming preferences", "user_id": "testuser", "limit": 5}' run "POST /memories/recent" \ -X POST "$BASE/memories/recent" \ -H "Content-Type: application/json" \ -d '{"user_id": "testuser", "limit": 5}' # ───────────────────────────────────────────── sep "/knowledge (objective facts — book-ingestor)" # ───────────────────────────────────────────── run "POST /knowledge — Gesell with metadata (LLM extraction)" \ -X POST "$BASE/knowledge" \ -H "Content-Type: application/json" \ -d '{ "text": "Silvio Gesell proposed demurrage as a mechanism to discourage hoarding of currency. He described this in The Natural Economic Order published in 1916.", "user_id": "knowledge_base", "metadata": {"source_file": "gesell_neo.pdf", "chapter": 3, "page": 47} }' run "POST /knowledge — MIDI verbatim (infer:false)" \ -X POST "$BASE/knowledge" \ -H "Content-Type: application/json" \ -d '{ "text": "MIDI SysEx messages use a 7-bit checksum computed as the twos complement of the sum of all data bytes.", "user_id": "knowledge_base", "infer": false, "metadata": {"source_file": "midi_spec.pdf", "chapter": 9, "page": 112} }' run "POST /knowledge/search — Gesell demurrage (should NOT return MIDI)" \ -X POST "$BASE/knowledge/search" \ -H "Content-Type: application/json" \ -d '{"query": "Gesell demurrage", "user_id": "knowledge_base", "limit": 5}' run "POST /knowledge/search — free money currency hoarding" \ -X POST "$BASE/knowledge/search" \ -H "Content-Type: application/json" \ -d '{"query": "free money currency hoarding", "user_id": "knowledge_base", "limit": 5}' run "POST /knowledge/search — MIDI checksum (should NOT return Gesell)" \ -X POST "$BASE/knowledge/search" \ -H "Content-Type: application/json" \ -d '{"query": "MIDI checksum SysEx", "user_id": "knowledge_base", "limit": 5}' run "POST /knowledge/recent" \ -X POST "$BASE/knowledge/recent" \ -H "Content-Type: application/json" \ -d '{"user_id": "knowledge_base", "limit": 5}' # ───────────────────────────────────────────── sep "/search (merged — both collections)" # ───────────────────────────────────────────── run "POST /search — Python programming (expect _source tags on results)" \ -X POST "$BASE/search" \ -H "Content-Type: application/json" \ -d '{"query": "Python programming", "user_id": "testuser", "limit": 8}' run "POST /search — Gesell economic theory (cross-collection)" \ -X POST "$BASE/search" \ -H "Content-Type: application/json" \ -d '{"query": "Gesell economic theory", "user_id": "knowledge_base", "limit": 5}' # ───────────────────────────────────────────── sep "ERROR HANDLING" # ───────────────────────────────────────────── run "POST /memories — missing text/messages (expect 400)" \ -X POST "$BASE/memories" \ -H "Content-Type: application/json" \ -d '{"user_id": "testuser"}' run "POST /memories — infer:false ignored on /memories (no verbatim)" \ -X POST "$BASE/memories" \ -H "Content-Type: application/json" \ -d '{"text": "This should still go through LLM extraction", "user_id": "testuser", "infer": false}' # ───────────────────────────────────────────── sep "DELETE (comment out if you want to keep test data)" # ───────────────────────────────────────────── # Uncomment to clean up after testing: # run "DELETE /memories — testuser" \ # -X DELETE "$BASE/memories" \ # -H "Content-Type: application/json" \ # -d '{"filter": {"user_id": "testuser"}}' # # run "DELETE /knowledge — knowledge_base" \ # -X DELETE "$BASE/knowledge" \ # -H "Content-Type: application/json" \ # -d '{"filter": {"user_id": "knowledge_base"}}' # ───────────────────────────────────────────── sep "RESULTS" # ───────────────────────────────────────────── echo -e "\n${BOLD}Passed: ${GREEN}$PASS${RESET} ${BOLD}Failed: ${RED}$FAIL${RESET}\n"