181 lines
7.5 KiB
Bash
Executable File
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 |