191 lines
5.1 KiB
Bash
191 lines
5.1 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
# Performance Testing Script
|
||
|
|
# Uses k6, Apache Bench, or curl for load testing
|
||
|
|
|
||
|
|
set -e
|
||
|
|
|
||
|
|
# Configuration
|
||
|
|
API_URL="${API_URL:-https://api.sankofa.nexus}"
|
||
|
|
PORTAL_URL="${PORTAL_URL:-https://portal.sankofa.nexus}"
|
||
|
|
TEST_DURATION="${TEST_DURATION:-60s}"
|
||
|
|
VUS="${VUS:-10}" # Virtual Users
|
||
|
|
|
||
|
|
# Colors
|
||
|
|
GREEN='\033[0;32m'
|
||
|
|
RED='\033[0;31m'
|
||
|
|
YELLOW='\033[1;33m'
|
||
|
|
NC='\033[0m'
|
||
|
|
|
||
|
|
log_info() {
|
||
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
||
|
|
}
|
||
|
|
|
||
|
|
log_error() {
|
||
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check for k6
|
||
|
|
if command -v k6 &> /dev/null; then
|
||
|
|
log_info "Using k6 for load testing"
|
||
|
|
USE_K6=true
|
||
|
|
elif command -v ab &> /dev/null; then
|
||
|
|
log_info "Using Apache Bench for load testing"
|
||
|
|
USE_K6=false
|
||
|
|
USE_AB=true
|
||
|
|
else
|
||
|
|
log_error "Neither k6 nor Apache Bench found. Install k6: https://k6.io/docs/getting-started/installation/"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Create k6 test script
|
||
|
|
create_k6_script() {
|
||
|
|
cat > /tmp/k6_test.js << 'EOF'
|
||
|
|
import http from 'k6/http';
|
||
|
|
import { check, sleep } from 'k6';
|
||
|
|
import { Rate } from 'k6/metrics';
|
||
|
|
|
||
|
|
const errorRate = new Rate('errors');
|
||
|
|
|
||
|
|
export const options = {
|
||
|
|
stages: [
|
||
|
|
{ duration: '30s', target: 10 }, // Ramp up
|
||
|
|
{ duration: '1m', target: 10 }, // Stay at 10 VUs
|
||
|
|
{ duration: '30s', target: 20 }, // Ramp up to 20
|
||
|
|
{ duration: '1m', target: 20 }, // Stay at 20 VUs
|
||
|
|
{ duration: '30s', target: 0 }, // Ramp down
|
||
|
|
],
|
||
|
|
thresholds: {
|
||
|
|
'http_req_duration': ['p(95)<200'], // 95% of requests should be below 200ms
|
||
|
|
'http_req_failed': ['rate<0.01'], // Error rate should be less than 1%
|
||
|
|
'errors': ['rate<0.01'],
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
const API_URL = __ENV.API_URL || 'https://api.sankofa.nexus';
|
||
|
|
|
||
|
|
export default function () {
|
||
|
|
// Test health endpoint
|
||
|
|
const healthRes = http.get(`${API_URL}/health`);
|
||
|
|
const healthCheck = check(healthRes, {
|
||
|
|
'health status is 200': (r) => r.status === 200,
|
||
|
|
'health response time < 100ms': (r) => r.timings.duration < 100,
|
||
|
|
});
|
||
|
|
errorRate.add(!healthCheck);
|
||
|
|
|
||
|
|
// Test GraphQL endpoint
|
||
|
|
const graphqlPayload = JSON.stringify({
|
||
|
|
query: '{ __typename }',
|
||
|
|
});
|
||
|
|
const graphqlRes = http.post(`${API_URL}/graphql`, graphqlPayload, {
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
});
|
||
|
|
const graphqlCheck = check(graphqlRes, {
|
||
|
|
'graphql status is 200': (r) => r.status === 200,
|
||
|
|
'graphql response time < 200ms': (r) => r.timings.duration < 200,
|
||
|
|
'graphql has data': (r) => JSON.parse(r.body).data !== undefined,
|
||
|
|
});
|
||
|
|
errorRate.add(!graphqlCheck);
|
||
|
|
|
||
|
|
sleep(1);
|
||
|
|
}
|
||
|
|
EOF
|
||
|
|
}
|
||
|
|
|
||
|
|
# Run k6 test
|
||
|
|
run_k6_test() {
|
||
|
|
log_info "Starting k6 load test..."
|
||
|
|
log_info "Duration: ${TEST_DURATION}"
|
||
|
|
log_info "Virtual Users: ${VUS}"
|
||
|
|
log_info "API URL: ${API_URL}"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
k6 run --env API_URL="${API_URL}" \
|
||
|
|
--duration "${TEST_DURATION}" \
|
||
|
|
--vus "${VUS}" \
|
||
|
|
/tmp/k6_test.js
|
||
|
|
}
|
||
|
|
|
||
|
|
# Run Apache Bench test
|
||
|
|
run_ab_test() {
|
||
|
|
log_info "Starting Apache Bench load test..."
|
||
|
|
log_info "Requests: 1000"
|
||
|
|
log_info "Concurrency: ${VUS}"
|
||
|
|
log_info "API URL: ${API_URL}"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# Test health endpoint
|
||
|
|
log_info "Testing /health endpoint..."
|
||
|
|
ab -n 1000 -c "${VUS}" -k "${API_URL}/health"
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
log_info "Testing GraphQL endpoint..."
|
||
|
|
echo '{"query": "{ __typename }"}' > /tmp/graphql_payload.json
|
||
|
|
ab -n 1000 -c "${VUS}" -k -p /tmp/graphql_payload.json \
|
||
|
|
-T 'application/json' \
|
||
|
|
"${API_URL}/graphql"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Simple curl-based test
|
||
|
|
run_curl_test() {
|
||
|
|
log_info "Running simple curl-based performance test..."
|
||
|
|
log_info "This is a basic test. For comprehensive testing, install k6."
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
local total_time=0
|
||
|
|
local success_count=0
|
||
|
|
local fail_count=0
|
||
|
|
local iterations=100
|
||
|
|
|
||
|
|
for i in $(seq 1 $iterations); do
|
||
|
|
start=$(date +%s%N)
|
||
|
|
if curl -sf "${API_URL}/health" > /dev/null; then
|
||
|
|
end=$(date +%s%N)
|
||
|
|
duration=$(( (end - start) / 1000000 )) # Convert to milliseconds
|
||
|
|
total_time=$((total_time + duration))
|
||
|
|
((success_count++))
|
||
|
|
else
|
||
|
|
((fail_count++))
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
if [ $success_count -gt 0 ]; then
|
||
|
|
avg_time=$((total_time / success_count))
|
||
|
|
echo "Results:"
|
||
|
|
echo " Success: ${success_count}/${iterations}"
|
||
|
|
echo " Failed: ${fail_count}/${iterations}"
|
||
|
|
echo " Average response time: ${avg_time}ms"
|
||
|
|
|
||
|
|
if [ $avg_time -lt 200 ]; then
|
||
|
|
log_info "✓ Average response time is below 200ms target"
|
||
|
|
else
|
||
|
|
log_error "✗ Average response time exceeds 200ms target"
|
||
|
|
fi
|
||
|
|
else
|
||
|
|
log_error "All requests failed!"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Main execution
|
||
|
|
main() {
|
||
|
|
echo "=========================================="
|
||
|
|
echo "Sankofa Phoenix Performance Test"
|
||
|
|
echo "=========================================="
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
if [ "$USE_K6" = true ]; then
|
||
|
|
create_k6_script
|
||
|
|
run_k6_test
|
||
|
|
elif [ "$USE_AB" = true ]; then
|
||
|
|
run_ab_test
|
||
|
|
else
|
||
|
|
run_curl_test
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
log_info "Performance test completed!"
|
||
|
|
}
|
||
|
|
|
||
|
|
main "$@"
|
||
|
|
|