diff options
Diffstat (limited to 'bash/talk-to-computer/lil_tester.sh')
-rwxr-xr-x | bash/talk-to-computer/lil_tester.sh | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/bash/talk-to-computer/lil_tester.sh b/bash/talk-to-computer/lil_tester.sh new file mode 100755 index 0000000..8bdcc41 --- /dev/null +++ b/bash/talk-to-computer/lil_tester.sh @@ -0,0 +1,288 @@ +#!/bin/bash + +# Lil Script Tester - Secure Sandbox Testing Module +# This module provides secure testing capabilities for Lil scripts generated by the puzzle mechanism. +# +# SECURITY FEATURES: +# - Sandboxed execution environment +# - Resource limits (CPU, memory, time) +# - File system isolation +# - Network access prevention +# - Safe error handling +# - Result validation and sanitization + +# --- Configuration --- +TEST_TIMEOUT=10 # Maximum execution time in seconds +MAX_OUTPUT_SIZE=10000 # Maximum output size in characters +TEMP_DIR_BASE="/tmp/lil_test" # Base temporary directory +SAFE_COMMANDS=("print" "echo" "count" "first" "last" "sum" "min" "max" "range" "keys" "list" "table" "typeof" "mag" "unit") + +# --- Security Functions --- + +# Create secure temporary directory +create_secure_temp_dir() { + local dir="$1" + mkdir -p "$dir" + chmod 700 "$dir" + + # Create a minimal environment + echo "()" > "$dir/empty.lil" + echo "nil" > "$dir/nil.lil" +} + +# Clean up temporary directory +cleanup_temp_dir() { + local dir="$1" + if [ -d "$dir" ]; then + rm -rf "$dir" 2>/dev/null + fi +} + +# Validate Lil code for potentially dangerous operations +validate_lil_code() { + local code="$1" + + # Check for potentially dangerous patterns + local dangerous_patterns=( + "system\\[" # System calls + "exec\\[" # Execution + "file\\." # File operations + "network\\." # Network operations + "http\\." # HTTP requests + "shell\\[" # Shell execution + "\\$\\(" # Command substitution + "\\`.*\\`" # Backtick execution + ) + + for pattern in "${dangerous_patterns[@]}"; do + if echo "$code" | grep -q "$pattern" 2>/dev/null; then + echo "DANGEROUS_CODE_DETECTED: $pattern" + return 1 + fi + done + + # Check for reasonable complexity (prevent infinite loops) + local line_count=$(echo "$code" | wc -l) + if [ "$line_count" -gt 100 ]; then + echo "CODE_TOO_COMPLEX: $line_count lines (max: 100)" + return 1 + fi + + echo "CODE_VALIDATED" + return 0 +} + +# Create a safe test wrapper +create_safe_test_wrapper() { + local code="$1" + local test_name="$2" + local temp_dir="$3" + + # Create a safe test file + cat > "$temp_dir/test_$test_name.lil" << EOF +# Safe test wrapper for: $test_name +# Generated by Lil Tester + +# Set safe defaults +on safe_test do + local result + local error_occurred + + # Wrap execution in error handling + on execute_safely do + $code + end + + # Execute and capture result + result:execute_safely() + + # Return result or error indicator + if result = nil + "ERROR: Execution failed or returned nil" + else + result + end +end + +# Run the test +safe_test() +EOF +} + +# Execute Lil code safely +execute_lil_safely() { + local code="$1" + local test_name="$2" + local temp_dir="$3" + + # Validate code first + local validation_result=$(validate_lil_code "$code") + if [ $? -ne 0 ]; then + echo "VALIDATION_FAILED: $validation_result" + return 1 + fi + + # Create safe test wrapper + create_safe_test_wrapper "$code" "$test_name" "$temp_dir" + + # Try lilt first, fallback to lila + local result="" + local exit_code=1 + + # Test with lilt + if command -v lilt >/dev/null 2>&1; then + echo "Testing with lilt..." + result=$(timeout "$TEST_TIMEOUT" lilt "$temp_dir/test_$test_name.lil" 2>&1) + exit_code=$? + + if [ $exit_code -eq 0 ]; then + echo "SUCCESS: lilt execution completed" + else + echo "lilt failed, trying lila..." + fi + fi + + # Fallback to lila if lilt failed + if [ $exit_code -ne 0 ] && command -v lila >/dev/null 2>&1; then + echo "Testing with lila..." + result=$(timeout "$TEST_TIMEOUT" lila "$temp_dir/test_$test_name.lil" 2>&1) + exit_code=$? + + if [ $exit_code -eq 0 ]; then + echo "SUCCESS: lila execution completed" + else + echo "Both lilt and lila failed" + fi + fi + + # Check output size + local output_size=${#result} + if [ "$output_size" -gt "$MAX_OUTPUT_SIZE" ]; then + result="$(echo "$result" | head -c "$MAX_OUTPUT_SIZE")... [TRUNCATED]" + fi + + echo "$result" + return $exit_code +} + +# Run comprehensive tests +run_lil_tests() { + local code="$1" + local test_name="$2" + + # Create unique temporary directory + local temp_dir="${TEMP_DIR_BASE}_$$_$(date +%s)" + + echo "=== Lil Script Testing ===" + echo "Test Name: $test_name" + echo "Code Length: $(echo "$code" | wc -c) characters" + echo "----------------------------------------" + + # Create secure temporary directory + create_secure_temp_dir "$temp_dir" + + # Trap cleanup on exit + trap 'cleanup_temp_dir "$temp_dir"' EXIT + + # Execute the code safely + local start_time=$(date +%s.%N) + local result=$(execute_lil_safely "$code" "$test_name" "$temp_dir") + local exit_code=$? + local end_time=$(date +%s.%N) + + # Calculate execution time + local duration=$(echo "$end_time - $start_time" | bc -l 2>/dev/null || echo "0") + + # Report results + echo "----------------------------------------" + echo "Test Results:" + echo "Exit Code: $exit_code" + echo "Execution Time: ${duration}s" + echo "Output:" + echo "$result" + + if [ $exit_code -eq 0 ]; then + echo "✅ Test PASSED" + return 0 + else + echo "❌ Test FAILED" + return 1 + fi +} + +# Test specific Lil constructs +test_lil_constructs() { + local code="$1" + local test_name="$2" + + # Create unique temporary directory for construct testing + local temp_dir="${TEMP_DIR_BASE}_constructs_$$_$(date +%s)" + + echo "=== Lil Construct Testing ===" + echo "Testing specific Lil language features..." + + # Create and cleanup temp dir + create_secure_temp_dir "$temp_dir" + trap 'cleanup_temp_dir "$temp_dir"' EXIT + + # Test basic operations + local basic_tests=( + "Basic arithmetic: 2+3*4" + "List operations: (1,2,3) take 2" + "Dictionary: dict (\"a\",1) (\"b\",2)" + "Function definition: on test do 42 end" + ) + + for test in "${basic_tests[@]}"; do + local test_desc=$(echo "$test" | cut -d: -f1) + local test_code=$(echo "$test" | cut -d: -f2) + + echo "Testing: $test_desc" + local result=$(execute_lil_safely "$test_code" "basic_$test_desc" "$temp_dir") + + if [ $? -eq 0 ]; then + echo " ✅ $test_desc: PASSED" + else + echo " ❌ $test_desc: FAILED" + fi + done +} + +# Main testing interface +test_lil_script() { + local code="$1" + local test_name="${2:-unnamed_test}" + + if [ -z "$code" ]; then + echo "Error: No code provided for testing" + return 1 + fi + + # Run the main test + run_lil_tests "$code" "$test_name" + local main_result=$? + + # Run construct-specific tests + test_lil_constructs "$code" "$test_name" + + return $main_result +} + +# Export functions for use by other scripts +export -f test_lil_script +export -f run_lil_tests +export -f execute_lil_safely +export -f validate_lil_code +export -f create_secure_temp_dir +export -f cleanup_temp_dir + +# If run directly, provide usage information +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + if [ "$#" -lt 1 ]; then + echo "Usage: $0 <lil_code> [test_name]" + echo "Example: $0 'on test do 42 end' 'simple_function'" + exit 1 + fi + + test_lil_script "$1" "${2:-unnamed_test}" +fi |