#!/usr/bin/env crystal # Comprehensive tests for un.cr (Crystal UN CLI Inception implementation) # Compile and run with: crystal test_un_cr.cr require "http/client" require "json" # Color codes GREEN = "\033[32m" RED = "\033[31m" BLUE = "\033[34m" RESET = "\033[0m" # Test counters - use class with class variables class TestCounter @@passed = 0 @@failed = 0 def self.passed @@passed end def self.failed @@failed end def self.inc_passed @@passed += 1 end def self.inc_failed @@failed += 1 end end # Extension to language mapping (from un.cr) EXT_MAP = { ".jl" => "julia", ".r" => "r", ".cr" => "crystal", ".f90" => "fortran", ".cob" => "cobol", ".pro" => "prolog", ".forth" => "forth", ".4th" => "forth", ".py" => "python", ".js" => "javascript", ".rb" => "ruby", ".go" => "go", ".rs" => "rust", ".c" => "c", ".cpp" => "cpp", ".java" => "java", ".sh" => "bash" } def detect_language(filename : String) : String ext = File.extname(filename).downcase EXT_MAP.fetch(ext, "unknown") end def print_test(name : String, result : Bool) if result puts "#{GREEN}✓ PASS#{RESET}: #{name}" TestCounter.inc_passed else puts "#{RED}✗ FAIL#{RESET}: #{name}" TestCounter.inc_failed end end puts "\n#{BLUE}========================================#{RESET}" puts "#{BLUE}UN CLI Inception Tests - Crystal#{RESET}" puts "#{BLUE}========================================#{RESET}\n" # Test 1: Extension detection tests puts "#{BLUE}Test Suite 1: Extension Detection#{RESET}" print_test("Detect .jl as julia", detect_language("test.jl") == "julia") print_test("Detect .r as r", detect_language("test.r") == "r") print_test("Detect .cr as crystal", detect_language("test.cr") == "crystal") print_test("Detect .f90 as fortran", detect_language("test.f90") == "fortran") print_test("Detect .cob as cobol", detect_language("test.cob") == "cobol") print_test("Detect .pro as prolog", detect_language("test.pro") == "prolog") print_test("Detect .forth as forth", detect_language("test.forth") == "forth") print_test("Detect .4th as forth", detect_language("test.4th") == "forth") print_test("Detect .py as python", detect_language("test.py") == "python") print_test("Detect .rs as rust", detect_language("test.rs") == "rust") print_test("Detect unknown extension", detect_language("test.xyz") == "unknown") # Test 2: API Integration Test puts "\n#{BLUE}Test Suite 2: API Integration#{RESET}" api_key = ENV["UNSANDBOX_API_KEY"]? if api_key.nil? || api_key.empty? puts "#{BLUE}ℹ SKIP#{RESET}: API integration test (UNSANDBOX_API_KEY not set)" else begin url = URI.parse("https://api.unsandbox.com/execute") headers = HTTP::Headers{ "Content-Type" => "application/json", "Authorization" => "Bearer #{api_key}" } body = { language: "python", code: "print('Hello from test')" }.to_json response = HTTP::Client.post(url, headers: headers, body: body) result = JSON.parse(response.body) stdout = result["stdout"]? api_works = !stdout.nil? && stdout.as_s.includes?("Hello from test") print_test("API endpoint reachable and functional", api_works) rescue ex print_test("API endpoint reachable and functional", false) puts " Error: #{ex.message}" end end # Test 3: End-to-end functional test puts "\n#{BLUE}Test Suite 3: End-to-End Functional Test#{RESET}" if api_key.nil? || api_key.empty? puts "#{BLUE}ℹ SKIP#{RESET}: E2E test (UNSANDBOX_API_KEY not set)" else fib_file = "../../test/fib.cr" fib_file = "/home/fox/git/unsandbox.com/cli/test/fib.cr" unless File.exists?(fib_file) if File.exists?(fib_file) begin un_script = "../un.cr" un_script = "/home/fox/git/unsandbox.com/cli/inception/un.cr" unless File.exists?(un_script) output = IO::Memory.new error = IO::Memory.new process = Process.run("crystal", args: ["run", un_script, fib_file], output: output, error: error) result = output.to_s + error.to_s has_fib10 = result.includes?("fib(10) = 55") has_fib5 = result.includes?("fib(5) = 5") has_fib0 = result.includes?("fib(0) = 0") print_test("E2E: fib.cr produces fib(10) = 55", has_fib10) print_test("E2E: fib.cr produces fib(5) = 5", has_fib5) print_test("E2E: fib.cr produces fib(0) = 0", has_fib0) rescue ex print_test("E2E: fib.cr execution", false) puts " Error: #{ex.message}" end else puts "#{BLUE}ℹ SKIP#{RESET}: E2E test (fib.cr not found at expected location)" end end # Test 4: Error handling tests puts "\n#{BLUE}Test Suite 4: Error Handling#{RESET}" print_test("Unknown extension returns 'unknown'", detect_language("file.unknown") == "unknown") print_test("Case insensitive detection", detect_language("TEST.CR") == "crystal") print_test("Multiple dots in filename", detect_language("my.test.py") == "python") # Test 5: CLI Command Tests (new features) puts "\n#{BLUE}Test Suite 5: CLI Command Tests (Feature Parity)#{RESET}" un_script = File.expand_path("../clients/crystal/sync/src/un.cr", File.dirname(__FILE__)) un_script = File.expand_path("../../clients/crystal/sync/src/un.cr", File.dirname(__FILE__)) unless File.exists?(un_script) if File.exists?(un_script) # Test: --help begin output = IO::Memory.new error = IO::Memory.new process = Process.run("crystal", args: ["run", un_script, "--", "--help"], output: output, error: error) result = output.to_s + error.to_s has_help = result.includes?("Usage") || result.includes?("usage") print_test("CLI: --help shows usage", has_help) rescue ex print_test("CLI: --help shows usage", false) puts " Error: #{ex.message}" end # Test: version command begin output = IO::Memory.new error = IO::Memory.new process = Process.run("crystal", args: ["run", un_script, "--", "version"], output: output, error: error) result = output.to_s + error.to_s has_version = result.includes?("version") || result.includes?("Version") print_test("CLI: version command works", has_version) rescue ex print_test("CLI: version command works", false) puts " Error: #{ex.message}" end # Test: health command (requires network) begin output = IO::Memory.new error = IO::Memory.new process = Process.run("crystal", args: ["run", un_script, "--", "health"], output: output, error: error) result = output.to_s + error.to_s has_health = result.includes?("health") || result.includes?("API") print_test("CLI: health command works", has_health) rescue ex print_test("CLI: health command works", false) puts " Error: #{ex.message}" end # Test: languages command begin output = IO::Memory.new error = IO::Memory.new process = Process.run("crystal", args: ["run", un_script, "--", "languages"], output: output, error: error) result = output.to_s + error.to_s # Should list languages or require auth has_langs = result.includes?("python") || result.includes?("Error") || result.includes?("API key") print_test("CLI: languages command works", has_langs) rescue ex print_test("CLI: languages command works", false) puts " Error: #{ex.message}" end else puts "#{BLUE}ℹ SKIP#{RESET}: CLI tests (un.cr not found at expected location: #{un_script})" end # Test 6: API Command Tests (require API key) puts "\n#{BLUE}Test Suite 6: API Command Tests (require auth)#{RESET}" public_key = ENV["UNSANDBOX_PUBLIC_KEY"]? secret_key = ENV["UNSANDBOX_SECRET_KEY"]? if (public_key.nil? || public_key.empty?) && (secret_key.nil? || secret_key.empty?) puts "#{BLUE}ℹ SKIP#{RESET}: API command tests (UNSANDBOX_PUBLIC_KEY/SECRET_KEY not set)" else if File.exists?(un_script) # Test: snapshot --list begin output = IO::Memory.new error = IO::Memory.new process = Process.run("crystal", args: ["run", un_script, "--", "snapshot", "--list"], output: output, error: error) result = output.to_s + error.to_s # Should return JSON or error message has_response = result.includes?("[") || result.includes?("{") || result.includes?("Error") || result.includes?("snapshots") print_test("CLI: snapshot --list works", has_response) rescue ex print_test("CLI: snapshot --list works", false) puts " Error: #{ex.message}" end # Test: session --list begin output = IO::Memory.new error = IO::Memory.new process = Process.run("crystal", args: ["run", un_script, "--", "session", "--list"], output: output, error: error) result = output.to_s + error.to_s has_response = result.includes?("[") || result.includes?("{") || result.includes?("Error") || result.includes?("sessions") print_test("CLI: session --list works", has_response) rescue ex print_test("CLI: session --list works", false) puts " Error: #{ex.message}" end # Test: service --list begin output = IO::Memory.new error = IO::Memory.new process = Process.run("crystal", args: ["run", un_script, "--", "service", "--list"], output: output, error: error) result = output.to_s + error.to_s has_response = result.includes?("[") || result.includes?("{") || result.includes?("Error") || result.includes?("services") print_test("CLI: service --list works", has_response) rescue ex print_test("CLI: service --list works", false) puts " Error: #{ex.message}" end # Test: image --list begin output = IO::Memory.new error = IO::Memory.new process = Process.run("crystal", args: ["run", un_script, "--", "image", "--list"], output: output, error: error) result = output.to_s + error.to_s has_response = result.includes?("[") || result.includes?("{") || result.includes?("Error") || result.includes?("images") print_test("CLI: image --list works", has_response) rescue ex print_test("CLI: image --list works", false) puts " Error: #{ex.message}" end else puts "#{BLUE}ℹ SKIP#{RESET}: API command tests (un.cr not found)" end end # Print summary puts "\n#{BLUE}========================================#{RESET}" puts "#{BLUE}Test Summary#{RESET}" puts "#{BLUE}========================================#{RESET}" puts "#{GREEN}Passed: #{TestCounter.passed}#{RESET}" puts "#{RED}Failed: #{TestCounter.failed}#{RESET}" puts "#{BLUE}Total: #{TestCounter.passed + TestCounter.failed}#{RESET}" if TestCounter.failed > 0 puts "\n#{RED}TESTS FAILED#{RESET}" exit 1 else puts "\n#{GREEN}ALL TESTS PASSED#{RESET}" exit 0 end