commit 08553befcfc976dcc78edc1d7aca909ea0262775 Author: Yiyuan Li Date: Fri Jan 9 05:48:14 2026 +0000 Add test.sh diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..00c4df3 --- /dev/null +++ b/test.sh @@ -0,0 +1,173 @@ +#!/bin/bash + +# Test push_swap with multiple sizes, memory leak check, and sorting verification + +COUNT=${1:-5} # Number of tests per size, default 5 + +# Detect OS and architecture +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + OS="linux" + CHECKER="./checker/checker_linux" +elif [[ "$OSTYPE" == "darwin"* ]]; then + OS="mac" + CHECKER="./checker/checker_Mac" +else + echo "Unsupported OS: $OSTYPE" + exit 1 +fi + +ARCH=$(uname -m) +echo "Detected OS: $OS ($ARCH)" +echo "Using checker: $CHECKER" + +# Test if checker works (x86_64 checker on arm64 may hang) +CHECKER_WORKS=true +if [ -x "$CHECKER" ]; then + test_result=$(echo "" | timeout 2 $CHECKER 1 2>/dev/null; echo $?) + if [ "$test_result" == "124" ]; then + echo "⚠ Checker timeout - may have architecture mismatch (x86_64 on arm64)" + CHECKER_WORKS=false + fi +fi +echo "" + +# Test sizes and their targets (official: 5->12, 100->700, 500->5500) +SIZES=(2 5 10 100 200 500) +TARGETS=(1 12 50 700 2000 5500) + +# Generate random numbers based on OS +generate_random() { + local size=$1 + if [[ "$OS" == "mac" ]]; then + jot $size 1 $size | sort -R | tr '\n' ' ' + else + shuf -i 1-$size | tr '\n' ' ' + fi +} + +# Run tests for each size +overall_pass=true + +for idx in "${!SIZES[@]}"; do + SIZE=${SIZES[$idx]} + TARGET=${TARGETS[$idx]} + + echo "============================================" + echo "Testing with $SIZE numbers (target: <= $TARGET ops)" + echo "============================================" + + total=0 + min=999999 + max=0 + all_sorted=true + + for i in $(seq 1 $COUNT); do + # Generate unique random numbers + ARG=$(generate_random $SIZE) + + # Run push_swap and capture output + OPS_OUTPUT=$(./push_swap $ARG 2>/dev/null) + ops=$(echo "$OPS_OUTPUT" | wc -l | tr -d ' ') + + # Handle empty output (already sorted) + if [ -z "$OPS_OUTPUT" ]; then + ops=0 + fi + + # Verify sorting with checker + if [ "$CHECKER_WORKS" = true ] && [ -x "$CHECKER" ]; then + # Handle empty operations (already sorted case) - use printf for true empty + if [ -z "$OPS_OUTPUT" ]; then + result=$(printf '' | timeout 5 $CHECKER $ARG 2>/dev/null) + else + result=$(printf '%s\n' "$OPS_OUTPUT" | timeout 5 $CHECKER $ARG 2>/dev/null) + fi + if [ "$result" == "OK" ]; then + sorted_status="✓" + else + sorted_status="✗" + all_sorted=false + fi + else + sorted_status="-" # Checker not available + fi + + # Update stats + total=$((total + ops)) + if [ $ops -lt $min ]; then min=$ops; fi + if [ $ops -gt $max ]; then max=$ops; fi + + echo "Run $i: $ops ops $sorted_status" + done + + avg=$((total / COUNT)) + echo "--------------------------------------------" + echo "Min: $min | Max: $max | Avg: $avg | Target: $TARGET" + + if [ $max -le $TARGET ]; then + echo "✓ PASS - Operations within benchmark" + else + echo "✗ FAIL - Max ($max) exceeds target ($TARGET)" + overall_pass=false + fi + + if [ "$CHECKER_WORKS" = true ]; then + if [ "$all_sorted" = true ]; then + echo "✓ PASS - All sorts verified correct" + else + echo "✗ FAIL - Some sorts incorrect" + overall_pass=false + fi + else + echo "- SKIP - Checker not available" + fi + echo "" +done + +# Memory leak check +echo "============================================" +echo "Memory Leak Check" +echo "============================================" + +ARG=$(generate_random 100) + +if [[ "$OS" == "mac" ]]; then + # macOS: use leaks command + echo "Running: leaks --atExit -- ./push_swap ..." + leaks_output=$(leaks --atExit -- ./push_swap $ARG 2>&1) + if echo "$leaks_output" | grep -q "0 leaks"; then + echo "✓ PASS - No memory leaks detected" + elif echo "$leaks_output" | grep -q "cannot examine"; then + echo "⚠ SKIP - leaks tool cannot examine process (SIP restriction)" + else + leak_count=$(echo "$leaks_output" | grep -o "[0-9]* leak" | head -1) + echo "✗ FAIL - Memory leaks detected: $leak_count" + overall_pass=false + fi +else + # Linux: use valgrind + if command -v valgrind &> /dev/null; then + echo "Running: valgrind --leak-check=full ./push_swap ..." + valgrind_output=$(valgrind --leak-check=full --error-exitcode=1 ./push_swap $ARG 2>&1 >/dev/null) + if [ $? -eq 0 ]; then + echo "✓ PASS - No memory leaks detected" + else + echo "✗ FAIL - Memory leaks detected" + overall_pass=false + fi + else + echo "⚠ SKIP - valgrind not installed" + fi +fi + +echo "" +echo "============================================" +echo "Final Result" +echo "============================================" +if [ "$overall_pass" = true ]; then + echo "✓ ALL TESTS PASSED" + exit 0 +else + echo "✗ SOME TESTS FAILED" + exit 1 +fi