Files
c-relay/tests/input_validation_tests.sh

181 lines
7.5 KiB
Bash
Executable File

#!/bin/bash
# Input Validation Test Suite for C-Relay
# Comprehensive testing of input boundary conditions and malformed data
set -e
# Configuration
RELAY_HOST="127.0.0.1"
RELAY_PORT="8888"
TEST_TIMEOUT=10
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Test counters
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
# Function to test input validation
test_input_validation() {
local description="$1"
local message="$2"
local expect_success="${3:-false}"
TOTAL_TESTS=$((TOTAL_TESTS + 1))
echo -n "Testing $description... "
# Send message via websocat and capture response
local response
response=$(echo "$message" | timeout $TEST_TIMEOUT websocat -B 1048576 ws://$RELAY_HOST:$RELAY_PORT 2>/dev/null | head -3 || echo 'TIMEOUT')
if [[ "$response" == "TIMEOUT" ]]; then
echo -e "${RED}FAILED${NC} - Connection timeout"
FAILED_TESTS=$((FAILED_TESTS + 1))
return 1
fi
# Check if response indicates success or proper error handling
if [[ "$expect_success" == "true" ]]; then
# Valid input should get EOSE, EVENT, NOTICE (non-error), or COUNT response
if [[ "$response" == *"EOSE"* ]] || [[ "$response" == *"EVENT"* ]] || [[ "$response" == *"COUNT"* ]] || [[ "$response" == *"NOTICE"* && ! "$response" == *"error:"* ]]; then
echo -e "${GREEN}PASSED${NC} - Input accepted correctly"
PASSED_TESTS=$((PASSED_TESTS + 1))
return 0
else
echo -e "${RED}FAILED${NC} - Valid input rejected: $response"
FAILED_TESTS=$((FAILED_TESTS + 1))
return 1
fi
else
# Invalid input should get error NOTICE, NOTICE, connection failure, or empty response (connection closed)
if [[ "$response" == *"error:"* ]] || [[ "$response" == *"NOTICE"* ]] || [[ "$response" == *"CONNECTION_FAILED"* ]] || [[ -z "$response" ]]; then
echo -e "${GREEN}PASSED${NC} - Invalid input properly rejected"
PASSED_TESTS=$((PASSED_TESTS + 1))
return 0
else
echo -e "${RED}FAILED${NC} - Invalid input not rejected: $response"
FAILED_TESTS=$((FAILED_TESTS + 1))
return 1
fi
fi
}
echo "=========================================="
echo "C-Relay Input Validation Test Suite"
echo "=========================================="
echo "Testing against relay at ws://$RELAY_HOST:$RELAY_PORT"
echo
# Test basic connectivity first
echo "=== Basic Connectivity Test ==="
test_input_validation "Basic connectivity" '["REQ","basic_test",{}]' true
echo
echo "=== Message Type Validation ==="
# Test invalid message types
test_input_validation "Invalid message type - string" '["INVALID","test",{}]' false
test_input_validation "Invalid message type - number" '[123,"test",{}]' false
test_input_validation "Invalid message type - null" '[null,"test",{}]' false
test_input_validation "Invalid message type - object" '[{"type":"invalid"},"test",{}]' false
test_input_validation "Empty message type" '["","test",{}]' false
test_input_validation "Very long message type" '["'$(printf 'a%.0s' {1..1000})'","test",{}]' false
echo
echo "=== Message Structure Validation ==="
# Test malformed message structures
test_input_validation "Too few arguments" '["REQ"]' false
test_input_validation "Too many arguments" '["REQ","test",{}, "extra"]' false
test_input_validation "Non-array message" '"not an array"' false
test_input_validation "Empty array" '[]' false
test_input_validation "Nested arrays incorrectly" '[["REQ","test",{}]]' false
echo
echo "=== Subscription ID Boundary Tests ==="
# Test subscription ID limits
test_input_validation "Valid subscription ID" '["REQ","valid_sub_123",{}]' true
test_input_validation "Empty subscription ID" '["REQ","",{}]' false
test_input_validation "Subscription ID with spaces" '["REQ","sub with spaces",{}]' false
test_input_validation "Subscription ID with newlines" '["REQ","sub\nwith\nlines",{}]' false
test_input_validation "Subscription ID with tabs" '["REQ","sub\twith\ttabs",{}]' false
test_input_validation "Subscription ID with control chars" '["REQ","sub\x01\x02",{}]' false
test_input_validation "Unicode subscription ID" '["REQ","test🚀",{}]' false
test_input_validation "Very long subscription ID" '["REQ","'$(printf 'a%.0s' {1..200})'",{}]' false
echo
echo "=== Filter Object Validation ==="
# Test filter object structure
test_input_validation "Valid empty filter" '["REQ","test",{}]' true
test_input_validation "Non-object filter" '["REQ","test","not an object"]' false
test_input_validation "Null filter" '["REQ","test",null]' false
test_input_validation "Array filter" '["REQ","test",[]]' false
test_input_validation "Filter with invalid keys" '["REQ","test",{"invalid_key":"value"}]' true
echo
echo "=== Authors Field Validation ==="
# Test authors field with valid 64-char hex pubkey
test_input_validation "Valid authors array" '["REQ","test",{"authors":["0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"]}]' true
test_input_validation "Empty authors array" '["REQ","test",{"authors":[]}]' true
test_input_validation "Non-array authors" '["REQ","test",{"authors":"not an array"}]' false
test_input_validation "Invalid hex in authors" '["REQ","test",{"authors":["invalid_hex"]}]' false
test_input_validation "Short pubkey in authors" '["REQ","test",{"authors":["0123456789abcdef"]}]' false
echo
echo "=== IDs Field Validation ==="
# Test ids field
test_input_validation "Valid ids array" '["REQ","test",{"ids":["0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"]}]' true
test_input_validation "Empty ids array" '["REQ","test",{"ids":[]}]' true
test_input_validation "Non-array ids" '["REQ","test",{"ids":"not an array"}]' false
echo
echo "=== Kinds Field Validation ==="
# Test kinds field
test_input_validation "Valid kinds array" '["REQ","test",{"kinds":[1,2,3]}]' true
test_input_validation "Empty kinds array" '["REQ","test",{"kinds":[]}]' true
test_input_validation "Non-array kinds" '["REQ","test",{"kinds":"not an array"}]' false
test_input_validation "String in kinds" '["REQ","test",{"kinds":["1"]}]' false
echo
echo "=== Timestamp Field Validation ==="
# Test timestamp fields
test_input_validation "Valid since timestamp" '["REQ","test",{"since":1234567890}]' true
test_input_validation "Valid until timestamp" '["REQ","test",{"until":1234567890}]' true
test_input_validation "String since timestamp" '["REQ","test",{"since":"1234567890"}]' false
test_input_validation "Negative timestamp" '["REQ","test",{"since":-1}]' false
echo
echo "=== Limit Field Validation ==="
# Test limit field
test_input_validation "Valid limit" '["REQ","test",{"limit":100}]' true
test_input_validation "Zero limit" '["REQ","test",{"limit":0}]' true
test_input_validation "String limit" '["REQ","test",{"limit":"100"}]' false
test_input_validation "Negative limit" '["REQ","test",{"limit":-1}]' false
echo
echo "=== Multiple Filters ==="
# Test multiple filters
test_input_validation "Two valid filters" '["REQ","test",{"kinds":[1]},{"kinds":[2]}]' true
test_input_validation "Many filters" '["REQ","test",{},{},{},{},{}]' true
echo
echo "=== Test Results ==="
echo "Total tests: $TOTAL_TESTS"
echo "Passed: $PASSED_TESTS"
echo "Failed: $FAILED_TESTS"
if [ $FAILED_TESTS -eq 0 ]; then
echo -e "${GREEN}✓ All input validation tests passed!${NC}"
echo "The relay properly validates input."
exit 0
else
echo -e "${RED}✗ Some input validation tests failed${NC}"
echo "The relay may have input validation issues."
exit 1
fi