diff --git a/clients/java/Makefile b/clients/java/Makefile new file mode 100644 index 0000000..4915796 --- /dev/null +++ b/clients/java/Makefile @@ -0,0 +1,248 @@ +# UN Java Client - Build and Test +# +# This client has two implementations: +# - sync/ : Synchronous Java SDK (HttpURLConnection) +# - async/ : Asynchronous Java SDK (CompletableFuture/HttpClient) +# +# Usage: +# make # Build all +# make test # Run all 4 test modes +# make test-cli # CLI mode only +# make test-library # Library mode only +# make test-integration # Integration mode only +# make test-functional # Functional mode only +# make build # Build JAR files +# make clean # Remove build artifacts +# +# Dependencies: +# Java 11+ (for HttpClient) +# Maven or Gradle + +.PHONY: all build test test-cli test-library test-integration test-functional +.PHONY: test-sync test-async clean help examples + +# Paths +ROOT_DIR := $(shell cd ../.. && pwd) +SYNC_DIR := sync +ASYNC_DIR := async + +# Java settings +JAVA := java +JAVAC := javac +MAVEN := mvn +GRADLE := gradle + +# Colors +GREEN := \033[32m +RED := \033[31m +YELLOW := \033[33m +NC := \033[0m + +.DEFAULT_GOAL := help + +help: + @echo "UN Java Client - Build and Test" + @echo "" + @echo "Build:" + @echo " make build Build all JARs" + @echo " make build-sync Build sync SDK" + @echo " make build-async Build async SDK" + @echo "" + @echo "Test (all 4 modes):" + @echo " make test All 4 modes for both sync and async" + @echo " make test-cli CLI mode (command-line interface)" + @echo " make test-library Library mode (JUnit tests)" + @echo " make test-integration Integration mode (API contract)" + @echo " make test-functional Functional mode (real-world scenarios)" + @echo "" + @echo "Test by SDK:" + @echo " make test-sync Test synchronous SDK" + @echo " make test-async Test asynchronous SDK" + @echo "" + @echo "Utility:" + @echo " make clean Remove build artifacts" + @echo " make deps Show required dependencies" + @echo "" + +all: build + +deps: + @echo "Required:" + @echo " Java 11+ (for HttpClient)" + @echo " Maven or Gradle" + @echo "" + @java -version 2>&1 | head -1 || echo "Java not installed" + @mvn --version 2>/dev/null | head -1 || echo "Maven not installed (optional)" + @gradle --version 2>/dev/null | head -1 || echo "Gradle not installed (optional)" + +# ============================================================================ +# BUILD +# ============================================================================ + +build: build-sync build-async + @echo "$(GREEN)✓ All Java SDKs built$(NC)" + +build-sync: + @echo "Building sync SDK..." + @if [ -f "$(SYNC_DIR)/pom.xml" ]; then \ + cd $(SYNC_DIR) && $(MAVEN) compile -q && echo "$(GREEN)✓$(NC) Sync SDK compiled (Maven)"; \ + elif [ -f "$(SYNC_DIR)/build.gradle" ]; then \ + cd $(SYNC_DIR) && $(GRADLE) build -q && echo "$(GREEN)✓$(NC) Sync SDK compiled (Gradle)"; \ + elif [ -d "$(SYNC_DIR)/src" ]; then \ + echo "$(YELLOW)⊘$(NC) Sync SDK needs pom.xml or build.gradle"; \ + else \ + echo "$(YELLOW)⊘$(NC) Sync SDK not found"; \ + fi + +build-async: + @echo "Building async SDK..." + @if [ -f "$(ASYNC_DIR)/pom.xml" ]; then \ + cd $(ASYNC_DIR) && $(MAVEN) compile -q && echo "$(GREEN)✓$(NC) Async SDK compiled (Maven)"; \ + elif [ -f "$(ASYNC_DIR)/build.gradle" ]; then \ + cd $(ASYNC_DIR) && $(GRADLE) build -q && echo "$(GREEN)✓$(NC) Async SDK compiled (Gradle)"; \ + elif [ -d "$(ASYNC_DIR)/src" ]; then \ + echo "$(YELLOW)⊘$(NC) Async SDK needs pom.xml or build.gradle"; \ + else \ + echo "$(YELLOW)⊘$(NC) Async SDK not found"; \ + fi + +# ============================================================================ +# TEST: All 4 Modes +# ============================================================================ + +test: test-cli test-library test-integration test-functional + @echo "" + @echo "$(GREEN)✓ Java Client: All 4 test modes complete$(NC)" + +# ============================================================================ +# TEST: CLI Mode +# ============================================================================ + +test-cli: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "CLI MODE: Testing Java CLI interface" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test sync SDK compile + @if [ -f "$(SYNC_DIR)/pom.xml" ]; then \ + cd $(SYNC_DIR) && $(MAVEN) compile -q 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Sync SDK compiles (Maven)" || echo " $(RED)✗$(NC) CLI: Sync SDK compile failed"; \ + elif [ -f "$(SYNC_DIR)/build.gradle" ]; then \ + cd $(SYNC_DIR) && $(GRADLE) compileJava -q 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Sync SDK compiles (Gradle)" || echo " $(RED)✗$(NC) CLI: Sync SDK compile failed"; \ + elif [ -d "$(SYNC_DIR)/src" ]; then \ + echo " $(YELLOW)⊘$(NC) CLI: Sync SDK needs build configuration"; \ + fi + @# Test async SDK compile + @if [ -f "$(ASYNC_DIR)/pom.xml" ]; then \ + cd $(ASYNC_DIR) && $(MAVEN) compile -q 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Async SDK compiles (Maven)" || echo " $(YELLOW)⊘$(NC) CLI: Async SDK not yet buildable"; \ + elif [ -f "$(ASYNC_DIR)/build.gradle" ]; then \ + cd $(ASYNC_DIR) && $(GRADLE) compileJava -q 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Async SDK compiles (Gradle)" || echo " $(YELLOW)⊘$(NC) CLI: Async SDK not yet buildable"; \ + fi + +# ============================================================================ +# TEST: Library Mode +# ============================================================================ + +test-library: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "LIBRARY MODE: Testing Java classes" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test sync SDK with Maven/Gradle test + @if [ -f "$(SYNC_DIR)/pom.xml" ]; then \ + cd $(SYNC_DIR) && $(MAVEN) test -q 2>&1 | tail -10 || echo " $(YELLOW)⊘$(NC) Library: Sync tests incomplete"; \ + elif [ -f "$(SYNC_DIR)/build.gradle" ]; then \ + cd $(SYNC_DIR) && $(GRADLE) test -q 2>&1 | tail -10 || echo " $(YELLOW)⊘$(NC) Library: Sync tests incomplete"; \ + else \ + echo " $(YELLOW)⊘$(NC) Library: Sync SDK needs build configuration"; \ + fi + @# Test async SDK + @if [ -f "$(ASYNC_DIR)/pom.xml" ]; then \ + cd $(ASYNC_DIR) && $(MAVEN) test -q 2>&1 | tail -10 || echo " $(YELLOW)⊘$(NC) Library: Async tests incomplete"; \ + elif [ -f "$(ASYNC_DIR)/build.gradle" ]; then \ + cd $(ASYNC_DIR) && $(GRADLE) test -q 2>&1 | tail -10 || echo " $(YELLOW)⊘$(NC) Library: Async tests incomplete"; \ + fi + +# ============================================================================ +# TEST: Integration Mode +# ============================================================================ + +test-integration: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "INTEGRATION MODE: Testing API contract" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + echo " Set UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY"; \ + else \ + echo " Testing API authentication..."; \ + echo " $(YELLOW)⊘$(NC) Integration: SDK not yet implemented"; \ + fi + +# ============================================================================ +# TEST: Functional Mode +# ============================================================================ + +test-functional: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "FUNCTIONAL MODE: Real-world scenarios" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + else \ + echo " Running functional tests..."; \ + echo " $(YELLOW)⊘$(NC) Functional: SDK not yet implemented"; \ + fi + +# ============================================================================ +# TEST: By SDK Type +# ============================================================================ + +test-sync: + @echo "Testing Sync SDK..." + @if [ -f "$(SYNC_DIR)/pom.xml" ]; then \ + cd $(SYNC_DIR) && $(MAVEN) test; \ + elif [ -f "$(SYNC_DIR)/build.gradle" ]; then \ + cd $(SYNC_DIR) && $(GRADLE) test; \ + else \ + echo " $(YELLOW)⊘$(NC) Sync SDK tests not found"; \ + fi + +test-async: + @echo "Testing Async SDK..." + @if [ -f "$(ASYNC_DIR)/pom.xml" ]; then \ + cd $(ASYNC_DIR) && $(MAVEN) test; \ + elif [ -f "$(ASYNC_DIR)/build.gradle" ]; then \ + cd $(ASYNC_DIR) && $(GRADLE) test; \ + else \ + echo " $(YELLOW)⊘$(NC) Async SDK tests not found"; \ + fi + +# ============================================================================ +# Examples +# ============================================================================ + +examples: + @echo "Running Java examples..." + @if [ -f "$(SYNC_DIR)/pom.xml" ]; then \ + cd $(SYNC_DIR) && $(MAVEN) exec:java -Dexec.mainClass="examples.HelloWorld" 2>&1 | head -10 || true; \ + fi + +# ============================================================================ +# Clean +# ============================================================================ + +clean: + @echo "Cleaning Java build artifacts..." + @if [ -f "$(SYNC_DIR)/pom.xml" ]; then cd $(SYNC_DIR) && $(MAVEN) clean -q 2>/dev/null || true; fi + @if [ -f "$(ASYNC_DIR)/pom.xml" ]; then cd $(ASYNC_DIR) && $(MAVEN) clean -q 2>/dev/null || true; fi + @if [ -f "$(SYNC_DIR)/build.gradle" ]; then cd $(SYNC_DIR) && $(GRADLE) clean -q 2>/dev/null || true; fi + @if [ -f "$(ASYNC_DIR)/build.gradle" ]; then cd $(ASYNC_DIR) && $(GRADLE) clean -q 2>/dev/null || true; fi + @rm -rf $(SYNC_DIR)/target $(ASYNC_DIR)/target 2>/dev/null || true + @rm -rf $(SYNC_DIR)/build $(ASYNC_DIR)/build 2>/dev/null || true + @echo "$(GREEN)✓$(NC) Cleaned build artifacts" diff --git a/clients/javascript/Makefile b/clients/javascript/Makefile new file mode 100644 index 0000000..abf6e20 --- /dev/null +++ b/clients/javascript/Makefile @@ -0,0 +1,234 @@ +# UN JavaScript Client - Build and Test +# +# This client has two implementations: +# - sync/ : Synchronous/Promise-based SDK (Node.js) +# - async/ : Async/Await SDK (Node.js) +# +# Usage: +# make # Run all tests +# make test # Run all 4 test modes +# make test-cli # CLI mode only +# make test-library # Library mode only +# make test-integration # Integration mode only +# make test-functional # Functional mode only +# make test-sync # Test sync SDK only +# make test-async # Test async SDK only +# make clean # Remove build artifacts +# +# Dependencies: +# npm install (or yarn install) + +.PHONY: all test test-cli test-library test-integration test-functional +.PHONY: test-sync test-async install dev-install lint format clean help examples + +# Paths +ROOT_DIR := $(shell cd ../.. && pwd) +SYNC_DIR := sync +ASYNC_DIR := async + +# Colors +GREEN := \033[32m +RED := \033[31m +YELLOW := \033[33m +NC := \033[0m + +.DEFAULT_GOAL := help + +help: + @echo "UN JavaScript Client - Build and Test" + @echo "" + @echo "Test (all 4 modes):" + @echo " make test All 4 modes for both sync and async" + @echo " make test-cli CLI mode (command-line interface)" + @echo " make test-library Library mode (require and use)" + @echo " make test-integration Integration mode (API contract)" + @echo " make test-functional Functional mode (real-world scenarios)" + @echo "" + @echo "Test by SDK:" + @echo " make test-sync Test synchronous SDK" + @echo " make test-async Test asynchronous SDK" + @echo "" + @echo "Development:" + @echo " make install Install dependencies" + @echo " make lint Lint with ESLint" + @echo " make format Format with Prettier" + @echo " make examples Run example scripts" + @echo "" + @echo "Utility:" + @echo " make clean Remove build artifacts" + @echo " make deps Show required dependencies" + @echo "" + +all: test + +deps: + @echo "Required packages:" + @echo " npm install jest eslint prettier" + @echo "" + @node --version 2>/dev/null || echo "Node.js not installed" + +# ============================================================================ +# TEST: All 4 Modes +# ============================================================================ + +test: test-cli test-library test-integration test-functional + @echo "" + @echo "$(GREEN)✓ JavaScript Client: All 4 test modes complete$(NC)" + +# ============================================================================ +# TEST: CLI Mode +# ============================================================================ + +test-cli: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "CLI MODE: Testing JavaScript CLI interface" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test root-level un.js if it exists + @if [ -f "$(ROOT_DIR)/un.js" ]; then \ + node --check "$(ROOT_DIR)/un.js" 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Syntax valid (un.js)" || echo " $(RED)✗$(NC) CLI: Syntax error in un.js"; \ + fi + @# Test sync SDK syntax + @if [ -f "$(SYNC_DIR)/src/un.js" ]; then \ + node --check "$(SYNC_DIR)/src/un.js" 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Sync SDK syntax valid" || echo " $(RED)✗$(NC) CLI: Sync SDK syntax error"; \ + fi + @# Test async SDK syntax + @if [ -f "$(ASYNC_DIR)/src/un.js" ]; then \ + node --check "$(ASYNC_DIR)/src/un.js" 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Async SDK syntax valid" || echo " $(YELLOW)⊘$(NC) CLI: Async SDK not yet implemented"; \ + fi + +# ============================================================================ +# TEST: Library Mode +# ============================================================================ + +test-library: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "LIBRARY MODE: Testing JavaScript imports" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test sync SDK import + @if [ -f "$(SYNC_DIR)/src/un.js" ]; then \ + node -e "const un = require('./$(SYNC_DIR)/src/un.js'); console.log(' ✓ Library: Sync SDK importable, exports:', Object.keys(un).length, 'functions')" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Library: Sync import needs dependencies"; \ + fi + @# Test async SDK import + @if [ -f "$(ASYNC_DIR)/src/un.js" ]; then \ + node -e "const un = require('./$(ASYNC_DIR)/src/un.js'); console.log(' ✓ Library: Async SDK importable')" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Library: Async SDK not yet implemented"; \ + fi + @# Run jest tests + @echo "" + @echo "Running unit tests..." + @if [ -d "$(SYNC_DIR)/tests" ] && [ -f "$(SYNC_DIR)/package.json" ]; then \ + cd $(SYNC_DIR) && npm test 2>/dev/null && echo " $(GREEN)✓$(NC) Sync SDK tests passed" || echo " $(YELLOW)⊘$(NC) Sync tests need: npm install"; \ + elif [ -d "$(SYNC_DIR)/tests" ]; then \ + echo " $(YELLOW)⊘$(NC) Sync tests need package.json"; \ + fi + @if [ -d "$(ASYNC_DIR)/tests" ] && [ -f "$(ASYNC_DIR)/package.json" ]; then \ + cd $(ASYNC_DIR) && npm test 2>/dev/null && echo " $(GREEN)✓$(NC) Async SDK tests passed" || echo " $(YELLOW)⊘$(NC) Async tests need: npm install"; \ + fi + +# ============================================================================ +# TEST: Integration Mode +# ============================================================================ + +test-integration: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "INTEGRATION MODE: Testing API contract" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + echo " Set UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY"; \ + else \ + echo " Testing API authentication..."; \ + if [ -f "$(SYNC_DIR)/src/un.js" ]; then \ + node -e "const un = require('./$(SYNC_DIR)/src/un.js'); un.executeCode('python', 'print(42)').then(r => { if(r.stdout && r.stdout.includes('42')) console.log(' ✓ Integration: API auth works'); else console.log(' ✗ Integration: Unexpected response'); }).catch(e => console.log(' ✗ Integration:', e.message))" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Integration: Check SDK"; \ + fi; \ + fi + +# ============================================================================ +# TEST: Functional Mode +# ============================================================================ + +test-functional: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "FUNCTIONAL MODE: Real-world scenarios" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + else \ + echo " Running functional tests..."; \ + if [ -f "$(SYNC_DIR)/src/un.js" ]; then \ + node -e "const un = require('./$(SYNC_DIR)/src/un.js'); un.executeCode('python', 'def fib(n): return n if n<2 else fib(n-1)+fib(n-2); print(fib(10))').then(r => { if(r.stdout && r.stdout.includes('55')) console.log(' ✓ Functional: Fibonacci'); else console.log(' ⊘ Functional: Check output'); }).catch(e => console.log(' ⊘ Functional:', e.message))" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Functional: Check SDK"; \ + fi; \ + fi + +# ============================================================================ +# TEST: By SDK Type +# ============================================================================ + +test-sync: + @echo "Testing Sync SDK..." + @if [ -f "$(SYNC_DIR)/package.json" ]; then \ + cd $(SYNC_DIR) && npm test; \ + elif [ -d "$(SYNC_DIR)/tests" ]; then \ + echo " $(YELLOW)⊘$(NC) Sync SDK needs package.json with test script"; \ + else \ + echo " $(YELLOW)⊘$(NC) Sync SDK tests not found"; \ + fi + +test-async: + @echo "Testing Async SDK..." + @if [ -f "$(ASYNC_DIR)/package.json" ]; then \ + cd $(ASYNC_DIR) && npm test; \ + elif [ -d "$(ASYNC_DIR)/tests" ]; then \ + echo " $(YELLOW)⊘$(NC) Async SDK needs package.json with test script"; \ + else \ + echo " $(YELLOW)⊘$(NC) Async SDK tests not found"; \ + fi + +# ============================================================================ +# Development +# ============================================================================ + +install: + @echo "Installing JavaScript SDK dependencies..." + @if [ -f "$(SYNC_DIR)/package.json" ]; then cd $(SYNC_DIR) && npm install; fi + @if [ -f "$(ASYNC_DIR)/package.json" ]; then cd $(ASYNC_DIR) && npm install; fi + @echo "$(GREEN)✓$(NC) Installation complete" + +lint: + @echo "Linting JavaScript SDKs..." + @if [ -d "$(SYNC_DIR)/src" ]; then npx eslint $(SYNC_DIR)/src/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) ESLint not configured"; fi + @if [ -d "$(ASYNC_DIR)/src" ]; then npx eslint $(ASYNC_DIR)/src/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) ESLint not configured"; fi + @echo "$(GREEN)✓$(NC) Lint complete" + +format: + @echo "Formatting JavaScript SDKs..." + @if [ -d "$(SYNC_DIR)/src" ]; then npx prettier --write $(SYNC_DIR)/src/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) Prettier not installed"; fi + @if [ -d "$(ASYNC_DIR)/src" ]; then npx prettier --write $(ASYNC_DIR)/src/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) Prettier not installed"; fi + @echo "$(GREEN)✓$(NC) Format complete" + +examples: + @echo "Running JavaScript examples..." + @if [ -d "$(SYNC_DIR)/examples" ]; then \ + for f in $(SYNC_DIR)/examples/*.js; do \ + echo "Running $$f..."; \ + node "$$f" 2>&1 | head -10 || true; \ + done; \ + fi + +# ============================================================================ +# Clean +# ============================================================================ + +clean: + @echo "Cleaning JavaScript build artifacts..." + @rm -rf $(SYNC_DIR)/node_modules $(ASYNC_DIR)/node_modules 2>/dev/null || true + @rm -rf $(SYNC_DIR)/coverage $(ASYNC_DIR)/coverage 2>/dev/null || true + @rm -f $(SYNC_DIR)/package-lock.json $(ASYNC_DIR)/package-lock.json 2>/dev/null || true + @echo "$(GREEN)✓$(NC) Cleaned build artifacts" diff --git a/clients/php/Makefile b/clients/php/Makefile new file mode 100644 index 0000000..29b37f8 --- /dev/null +++ b/clients/php/Makefile @@ -0,0 +1,232 @@ +# UN PHP Client - Build and Test +# +# This client has two implementations: +# - sync/ : Synchronous PHP SDK (curl) +# - async/ : Asynchronous PHP SDK (ReactPHP/Amp) +# +# Usage: +# make # Run all tests +# make test # Run all 4 test modes +# make test-cli # CLI mode only +# make test-library # Library mode only +# make test-integration # Integration mode only +# make test-functional # Functional mode only +# make test-sync # Test sync SDK only +# make test-async # Test async SDK only +# make clean # Remove build artifacts +# +# Dependencies: +# composer require phpunit/phpunit + +.PHONY: all test test-cli test-library test-integration test-functional +.PHONY: test-sync test-async install dev-install lint format clean help examples + +# Paths +ROOT_DIR := $(shell cd ../.. && pwd) +SYNC_DIR := sync +ASYNC_DIR := async + +# Colors +GREEN := \033[32m +RED := \033[31m +YELLOW := \033[33m +NC := \033[0m + +.DEFAULT_GOAL := help + +help: + @echo "UN PHP Client - Build and Test" + @echo "" + @echo "Test (all 4 modes):" + @echo " make test All 4 modes for both sync and async" + @echo " make test-cli CLI mode (command-line interface)" + @echo " make test-library Library mode (require and use)" + @echo " make test-integration Integration mode (API contract)" + @echo " make test-functional Functional mode (real-world scenarios)" + @echo "" + @echo "Test by SDK:" + @echo " make test-sync Test synchronous SDK" + @echo " make test-async Test asynchronous SDK" + @echo "" + @echo "Development:" + @echo " make install Install dependencies" + @echo " make lint Lint with PHP_CodeSniffer" + @echo " make format Format with PHP-CS-Fixer" + @echo " make examples Run example scripts" + @echo "" + @echo "Utility:" + @echo " make clean Remove build artifacts" + @echo " make deps Show required dependencies" + @echo "" + +all: test + +deps: + @echo "Required packages:" + @echo " composer require phpunit/phpunit squizlabs/php_codesniffer" + @echo "" + @php --version 2>/dev/null || echo "PHP not installed" + @composer --version 2>/dev/null || echo "Composer not installed" + +# ============================================================================ +# TEST: All 4 Modes +# ============================================================================ + +test: test-cli test-library test-integration test-functional + @echo "" + @echo "$(GREEN)✓ PHP Client: All 4 test modes complete$(NC)" + +# ============================================================================ +# TEST: CLI Mode +# ============================================================================ + +test-cli: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "CLI MODE: Testing PHP CLI interface" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test root-level un.php if it exists + @if [ -f "$(ROOT_DIR)/un.php" ]; then \ + php -l "$(ROOT_DIR)/un.php" > /dev/null 2>&1 && echo " $(GREEN)✓$(NC) CLI: Syntax valid (un.php)" || echo " $(RED)✗$(NC) CLI: Syntax error in un.php"; \ + fi + @# Test sync SDK syntax + @if [ -f "$(SYNC_DIR)/src/Unsandbox.php" ]; then \ + php -l "$(SYNC_DIR)/src/Unsandbox.php" > /dev/null 2>&1 && echo " $(GREEN)✓$(NC) CLI: Sync SDK syntax valid" || echo " $(RED)✗$(NC) CLI: Sync SDK syntax error"; \ + elif [ -f "$(SYNC_DIR)/src/un.php" ]; then \ + php -l "$(SYNC_DIR)/src/un.php" > /dev/null 2>&1 && echo " $(GREEN)✓$(NC) CLI: Sync SDK syntax valid" || echo " $(RED)✗$(NC) CLI: Sync SDK syntax error"; \ + fi + @# Test async SDK syntax + @if [ -f "$(ASYNC_DIR)/src/Unsandbox.php" ]; then \ + php -l "$(ASYNC_DIR)/src/Unsandbox.php" > /dev/null 2>&1 && echo " $(GREEN)✓$(NC) CLI: Async SDK syntax valid" || echo " $(YELLOW)⊘$(NC) CLI: Async SDK not yet implemented"; \ + fi + +# ============================================================================ +# TEST: Library Mode +# ============================================================================ + +test-library: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "LIBRARY MODE: Testing PHP imports" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test sync SDK import + @if [ -f "$(SYNC_DIR)/src/Unsandbox.php" ]; then \ + php -r "require '$(SYNC_DIR)/src/Unsandbox.php'; echo ' ✓ Library: Sync SDK importable\n';" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Library: Sync import needs dependencies"; \ + elif [ -f "$(SYNC_DIR)/src/un.php" ]; then \ + php -r "require '$(SYNC_DIR)/src/un.php'; echo ' ✓ Library: Sync SDK importable\n';" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Library: Sync import needs dependencies"; \ + fi + @# Test async SDK import + @if [ -f "$(ASYNC_DIR)/src/Unsandbox.php" ]; then \ + php -r "require '$(ASYNC_DIR)/src/Unsandbox.php'; echo ' ✓ Library: Async SDK importable\n';" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Library: Async import needs dependencies"; \ + fi + @# Run phpunit tests + @echo "" + @echo "Running unit tests..." + @if [ -d "$(SYNC_DIR)/tests" ] && [ -f "$(SYNC_DIR)/composer.json" ]; then \ + cd $(SYNC_DIR) && ./vendor/bin/phpunit tests/ 2>/dev/null && echo " $(GREEN)✓$(NC) Sync SDK tests passed" || echo " $(YELLOW)⊘$(NC) Sync tests need: composer install"; \ + fi + @if [ -d "$(ASYNC_DIR)/tests" ] && [ -f "$(ASYNC_DIR)/composer.json" ]; then \ + cd $(ASYNC_DIR) && ./vendor/bin/phpunit tests/ 2>/dev/null && echo " $(GREEN)✓$(NC) Async SDK tests passed" || echo " $(YELLOW)⊘$(NC) Async tests need: composer install"; \ + fi + +# ============================================================================ +# TEST: Integration Mode +# ============================================================================ + +test-integration: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "INTEGRATION MODE: Testing API contract" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + echo " Set UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY"; \ + else \ + echo " Testing API authentication..."; \ + echo " $(YELLOW)⊘$(NC) Integration: SDK not yet implemented"; \ + fi + +# ============================================================================ +# TEST: Functional Mode +# ============================================================================ + +test-functional: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "FUNCTIONAL MODE: Real-world scenarios" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + else \ + echo " Running functional tests..."; \ + echo " $(YELLOW)⊘$(NC) Functional: SDK not yet implemented"; \ + fi + +# ============================================================================ +# TEST: By SDK Type +# ============================================================================ + +test-sync: + @echo "Testing Sync SDK..." + @if [ -f "$(SYNC_DIR)/composer.json" ]; then \ + cd $(SYNC_DIR) && ./vendor/bin/phpunit tests/; \ + elif [ -d "$(SYNC_DIR)/tests" ]; then \ + cd $(SYNC_DIR) && phpunit tests/; \ + else \ + echo " $(YELLOW)⊘$(NC) Sync SDK tests not found"; \ + fi + +test-async: + @echo "Testing Async SDK..." + @if [ -f "$(ASYNC_DIR)/composer.json" ]; then \ + cd $(ASYNC_DIR) && ./vendor/bin/phpunit tests/; \ + elif [ -d "$(ASYNC_DIR)/tests" ]; then \ + cd $(ASYNC_DIR) && phpunit tests/; \ + else \ + echo " $(YELLOW)⊘$(NC) Async SDK tests not found"; \ + fi + +# ============================================================================ +# Development +# ============================================================================ + +install: + @echo "Installing PHP SDK dependencies..." + @if [ -f "$(SYNC_DIR)/composer.json" ]; then cd $(SYNC_DIR) && composer install; fi + @if [ -f "$(ASYNC_DIR)/composer.json" ]; then cd $(ASYNC_DIR) && composer install; fi + @echo "$(GREEN)✓$(NC) Installation complete" + +lint: + @echo "Linting PHP SDKs..." + @if [ -d "$(SYNC_DIR)/src" ]; then phpcs $(SYNC_DIR)/src/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) PHP_CodeSniffer not installed"; fi + @if [ -d "$(ASYNC_DIR)/src" ]; then phpcs $(ASYNC_DIR)/src/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) PHP_CodeSniffer not installed"; fi + @echo "$(GREEN)✓$(NC) Lint complete" + +format: + @echo "Formatting PHP SDKs..." + @if [ -d "$(SYNC_DIR)/src" ]; then php-cs-fixer fix $(SYNC_DIR)/src/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) PHP-CS-Fixer not installed"; fi + @if [ -d "$(ASYNC_DIR)/src" ]; then php-cs-fixer fix $(ASYNC_DIR)/src/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) PHP-CS-Fixer not installed"; fi + @echo "$(GREEN)✓$(NC) Format complete" + +examples: + @echo "Running PHP examples..." + @if [ -d "$(SYNC_DIR)/examples" ]; then \ + for f in $(SYNC_DIR)/examples/*.php; do \ + echo "Running $$f..."; \ + php "$$f" 2>&1 | head -10 || true; \ + done; \ + fi + +# ============================================================================ +# Clean +# ============================================================================ + +clean: + @echo "Cleaning PHP build artifacts..." + @rm -rf $(SYNC_DIR)/vendor $(ASYNC_DIR)/vendor 2>/dev/null || true + @rm -f $(SYNC_DIR)/composer.lock $(ASYNC_DIR)/composer.lock 2>/dev/null || true + @echo "$(GREEN)✓$(NC) Cleaned build artifacts" diff --git a/clients/ruby/Makefile b/clients/ruby/Makefile new file mode 100644 index 0000000..6657e0a --- /dev/null +++ b/clients/ruby/Makefile @@ -0,0 +1,232 @@ +# UN Ruby Client - Build and Test +# +# This client has two implementations: +# - sync/ : Synchronous Ruby SDK (net/http) +# - async/ : Asynchronous Ruby SDK (async-http) +# +# Usage: +# make # Run all tests +# make test # Run all 4 test modes +# make test-cli # CLI mode only +# make test-library # Library mode only +# make test-integration # Integration mode only +# make test-functional # Functional mode only +# make test-sync # Test sync SDK only +# make test-async # Test async SDK only +# make clean # Remove build artifacts +# +# Dependencies: +# gem install bundler rspec + +.PHONY: all test test-cli test-library test-integration test-functional +.PHONY: test-sync test-async install dev-install lint format clean help examples + +# Paths +ROOT_DIR := $(shell cd ../.. && pwd) +SYNC_DIR := sync +ASYNC_DIR := async + +# Colors +GREEN := \033[32m +RED := \033[31m +YELLOW := \033[33m +NC := \033[0m + +.DEFAULT_GOAL := help + +help: + @echo "UN Ruby Client - Build and Test" + @echo "" + @echo "Test (all 4 modes):" + @echo " make test All 4 modes for both sync and async" + @echo " make test-cli CLI mode (command-line interface)" + @echo " make test-library Library mode (require and use)" + @echo " make test-integration Integration mode (API contract)" + @echo " make test-functional Functional mode (real-world scenarios)" + @echo "" + @echo "Test by SDK:" + @echo " make test-sync Test synchronous SDK" + @echo " make test-async Test asynchronous SDK" + @echo "" + @echo "Development:" + @echo " make install Install dependencies" + @echo " make lint Lint with RuboCop" + @echo " make format Format with RuboCop" + @echo " make examples Run example scripts" + @echo "" + @echo "Utility:" + @echo " make clean Remove build artifacts" + @echo " make deps Show required dependencies" + @echo "" + +all: test + +deps: + @echo "Required packages:" + @echo " gem install bundler rspec rubocop" + @echo "" + @ruby --version 2>/dev/null || echo "Ruby not installed" + +# ============================================================================ +# TEST: All 4 Modes +# ============================================================================ + +test: test-cli test-library test-integration test-functional + @echo "" + @echo "$(GREEN)✓ Ruby Client: All 4 test modes complete$(NC)" + +# ============================================================================ +# TEST: CLI Mode +# ============================================================================ + +test-cli: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "CLI MODE: Testing Ruby CLI interface" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test root-level un.rb if it exists + @if [ -f "$(ROOT_DIR)/un.rb" ]; then \ + ruby -c "$(ROOT_DIR)/un.rb" > /dev/null 2>&1 && echo " $(GREEN)✓$(NC) CLI: Syntax valid (un.rb)" || echo " $(RED)✗$(NC) CLI: Syntax error in un.rb"; \ + fi + @# Test sync SDK syntax + @if [ -f "$(SYNC_DIR)/lib/unsandbox.rb" ]; then \ + ruby -c "$(SYNC_DIR)/lib/unsandbox.rb" > /dev/null 2>&1 && echo " $(GREEN)✓$(NC) CLI: Sync SDK syntax valid" || echo " $(RED)✗$(NC) CLI: Sync SDK syntax error"; \ + elif [ -f "$(SYNC_DIR)/src/un.rb" ]; then \ + ruby -c "$(SYNC_DIR)/src/un.rb" > /dev/null 2>&1 && echo " $(GREEN)✓$(NC) CLI: Sync SDK syntax valid" || echo " $(RED)✗$(NC) CLI: Sync SDK syntax error"; \ + fi + @# Test async SDK syntax + @if [ -f "$(ASYNC_DIR)/lib/unsandbox.rb" ]; then \ + ruby -c "$(ASYNC_DIR)/lib/unsandbox.rb" > /dev/null 2>&1 && echo " $(GREEN)✓$(NC) CLI: Async SDK syntax valid" || echo " $(YELLOW)⊘$(NC) CLI: Async SDK not yet implemented"; \ + fi + +# ============================================================================ +# TEST: Library Mode +# ============================================================================ + +test-library: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "LIBRARY MODE: Testing Ruby imports" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test sync SDK import + @if [ -f "$(SYNC_DIR)/lib/unsandbox.rb" ]; then \ + ruby -I$(SYNC_DIR)/lib -e "require 'unsandbox'; puts ' ✓ Library: Sync SDK importable'" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Library: Sync import needs dependencies"; \ + elif [ -f "$(SYNC_DIR)/src/un.rb" ]; then \ + ruby -I$(SYNC_DIR)/src -e "require 'un'; puts ' ✓ Library: Sync SDK importable'" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Library: Sync import needs dependencies"; \ + fi + @# Test async SDK import + @if [ -f "$(ASYNC_DIR)/lib/unsandbox.rb" ]; then \ + ruby -I$(ASYNC_DIR)/lib -e "require 'unsandbox'; puts ' ✓ Library: Async SDK importable'" 2>/dev/null || echo " $(YELLOW)⊘$(NC) Library: Async import needs dependencies"; \ + fi + @# Run rspec tests + @echo "" + @echo "Running unit tests..." + @if [ -d "$(SYNC_DIR)/spec" ]; then \ + cd $(SYNC_DIR) && bundle exec rspec spec/ 2>/dev/null && echo " $(GREEN)✓$(NC) Sync SDK tests passed" || echo " $(YELLOW)⊘$(NC) Sync tests need: bundle install"; \ + fi + @if [ -d "$(ASYNC_DIR)/spec" ]; then \ + cd $(ASYNC_DIR) && bundle exec rspec spec/ 2>/dev/null && echo " $(GREEN)✓$(NC) Async SDK tests passed" || echo " $(YELLOW)⊘$(NC) Async tests need: bundle install"; \ + fi + +# ============================================================================ +# TEST: Integration Mode +# ============================================================================ + +test-integration: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "INTEGRATION MODE: Testing API contract" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + echo " Set UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY"; \ + else \ + echo " Testing API authentication..."; \ + echo " $(YELLOW)⊘$(NC) Integration: SDK not yet implemented"; \ + fi + +# ============================================================================ +# TEST: Functional Mode +# ============================================================================ + +test-functional: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "FUNCTIONAL MODE: Real-world scenarios" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + else \ + echo " Running functional tests..."; \ + echo " $(YELLOW)⊘$(NC) Functional: SDK not yet implemented"; \ + fi + +# ============================================================================ +# TEST: By SDK Type +# ============================================================================ + +test-sync: + @echo "Testing Sync SDK..." + @if [ -f "$(SYNC_DIR)/Gemfile" ]; then \ + cd $(SYNC_DIR) && bundle exec rspec spec/; \ + elif [ -d "$(SYNC_DIR)/spec" ]; then \ + cd $(SYNC_DIR) && rspec spec/; \ + else \ + echo " $(YELLOW)⊘$(NC) Sync SDK tests not found"; \ + fi + +test-async: + @echo "Testing Async SDK..." + @if [ -f "$(ASYNC_DIR)/Gemfile" ]; then \ + cd $(ASYNC_DIR) && bundle exec rspec spec/; \ + elif [ -d "$(ASYNC_DIR)/spec" ]; then \ + cd $(ASYNC_DIR) && rspec spec/; \ + else \ + echo " $(YELLOW)⊘$(NC) Async SDK tests not found"; \ + fi + +# ============================================================================ +# Development +# ============================================================================ + +install: + @echo "Installing Ruby SDK dependencies..." + @if [ -f "$(SYNC_DIR)/Gemfile" ]; then cd $(SYNC_DIR) && bundle install; fi + @if [ -f "$(ASYNC_DIR)/Gemfile" ]; then cd $(ASYNC_DIR) && bundle install; fi + @echo "$(GREEN)✓$(NC) Installation complete" + +lint: + @echo "Linting Ruby SDKs..." + @if [ -d "$(SYNC_DIR)/lib" ]; then rubocop $(SYNC_DIR)/lib/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) RuboCop not installed"; fi + @if [ -d "$(ASYNC_DIR)/lib" ]; then rubocop $(ASYNC_DIR)/lib/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) RuboCop not installed"; fi + @echo "$(GREEN)✓$(NC) Lint complete" + +format: + @echo "Formatting Ruby SDKs..." + @if [ -d "$(SYNC_DIR)/lib" ]; then rubocop -a $(SYNC_DIR)/lib/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) RuboCop not installed"; fi + @if [ -d "$(ASYNC_DIR)/lib" ]; then rubocop -a $(ASYNC_DIR)/lib/ 2>/dev/null || echo " $(YELLOW)⊘$(NC) RuboCop not installed"; fi + @echo "$(GREEN)✓$(NC) Format complete" + +examples: + @echo "Running Ruby examples..." + @if [ -d "$(SYNC_DIR)/examples" ]; then \ + for f in $(SYNC_DIR)/examples/*.rb; do \ + echo "Running $$f..."; \ + ruby "$$f" 2>&1 | head -10 || true; \ + done; \ + fi + +# ============================================================================ +# Clean +# ============================================================================ + +clean: + @echo "Cleaning Ruby build artifacts..." + @find . -name "*.gem" -delete 2>/dev/null || true + @find . -name "Gemfile.lock" -delete 2>/dev/null || true + @rm -rf $(SYNC_DIR)/pkg $(ASYNC_DIR)/pkg 2>/dev/null || true + @echo "$(GREEN)✓$(NC) Cleaned build artifacts" diff --git a/clients/rust/Makefile b/clients/rust/Makefile new file mode 100644 index 0000000..1134b09 --- /dev/null +++ b/clients/rust/Makefile @@ -0,0 +1,258 @@ +# UN Rust Client - Build and Test +# +# This client has two implementations: +# - sync/ : Synchronous Rust SDK (blocking reqwest) +# - async/ : Asynchronous Rust SDK (tokio + async reqwest) +# +# Usage: +# make # Build all +# make test # Run all 4 test modes +# make test-cli # CLI mode only +# make test-library # Library mode only +# make test-integration # Integration mode only +# make test-functional # Functional mode only +# make build # Build binaries +# make clean # Remove build artifacts +# +# Dependencies: +# rustup (https://rustup.rs/) +# cargo + +.PHONY: all build test test-cli test-library test-integration test-functional +.PHONY: test-sync test-async clean help examples fmt clippy doc + +# Paths +ROOT_DIR := $(shell cd ../.. && pwd) +SYNC_DIR := sync +ASYNC_DIR := async + +# Colors +GREEN := \033[32m +RED := \033[31m +YELLOW := \033[33m +NC := \033[0m + +.DEFAULT_GOAL := help + +help: + @echo "UN Rust Client - Build and Test" + @echo "" + @echo "Build:" + @echo " make build Build all binaries" + @echo " make build-sync Build sync SDK" + @echo " make build-async Build async SDK" + @echo "" + @echo "Test (all 4 modes):" + @echo " make test All 4 modes for both sync and async" + @echo " make test-cli CLI mode (command-line interface)" + @echo " make test-library Library mode (cargo test)" + @echo " make test-integration Integration mode (API contract)" + @echo " make test-functional Functional mode (real-world scenarios)" + @echo "" + @echo "Test by SDK:" + @echo " make test-sync Test synchronous SDK" + @echo " make test-async Test asynchronous SDK" + @echo "" + @echo "Code Quality:" + @echo " make fmt Format with rustfmt" + @echo " make clippy Lint with clippy" + @echo " make doc Generate documentation" + @echo "" + @echo "Utility:" + @echo " make clean Remove build artifacts" + @echo " make deps Show required dependencies" + @echo "" + +all: build + +deps: + @echo "Required:" + @echo " rustup (https://rustup.rs/)" + @echo "" + @rustc --version 2>/dev/null || echo "Rust not installed" + @cargo --version 2>/dev/null || echo "Cargo not installed" + +# ============================================================================ +# BUILD +# ============================================================================ + +build: build-sync build-async + @echo "$(GREEN)✓ All Rust SDKs built$(NC)" + +build-sync: + @echo "Building sync SDK..." + @if [ -f "$(SYNC_DIR)/Cargo.toml" ]; then \ + cd $(SYNC_DIR) && cargo build --release 2>&1 | tail -5 && echo "$(GREEN)✓$(NC) Sync SDK compiled"; \ + elif [ -d "$(SYNC_DIR)/src" ]; then \ + echo "$(YELLOW)⊘$(NC) Sync SDK needs Cargo.toml"; \ + else \ + echo "$(YELLOW)⊘$(NC) Sync SDK not found"; \ + fi + +build-async: + @echo "Building async SDK..." + @if [ -f "$(ASYNC_DIR)/Cargo.toml" ]; then \ + cd $(ASYNC_DIR) && cargo build --release 2>&1 | tail -5 && echo "$(GREEN)✓$(NC) Async SDK compiled"; \ + elif [ -d "$(ASYNC_DIR)/src" ]; then \ + echo "$(YELLOW)⊘$(NC) Async SDK needs Cargo.toml"; \ + else \ + echo "$(YELLOW)⊘$(NC) Async SDK not found"; \ + fi + +# ============================================================================ +# TEST: All 4 Modes +# ============================================================================ + +test: test-cli test-library test-integration test-functional + @echo "" + @echo "$(GREEN)✓ Rust Client: All 4 test modes complete$(NC)" + +# ============================================================================ +# TEST: CLI Mode +# ============================================================================ + +test-cli: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "CLI MODE: Testing Rust CLI interface" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test root-level un.rs if it exists + @if [ -f "$(ROOT_DIR)/un.rs" ]; then \ + rustc --edition 2021 --emit=metadata "$(ROOT_DIR)/un.rs" -o /tmp/un_check 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Root un.rs syntax valid" || echo " $(YELLOW)⊘$(NC) CLI: Root un.rs (check dependencies)"; \ + rm -f /tmp/un_check 2>/dev/null; \ + fi + @# Test sync SDK compile + @if [ -f "$(SYNC_DIR)/Cargo.toml" ]; then \ + cd $(SYNC_DIR) && cargo check 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Sync SDK compiles" || echo " $(RED)✗$(NC) CLI: Sync SDK compile failed"; \ + fi + @# Test async SDK compile + @if [ -f "$(ASYNC_DIR)/Cargo.toml" ]; then \ + cd $(ASYNC_DIR) && cargo check 2>/dev/null && echo " $(GREEN)✓$(NC) CLI: Async SDK compiles" || echo " $(YELLOW)⊘$(NC) CLI: Async SDK not yet buildable"; \ + fi + +# ============================================================================ +# TEST: Library Mode +# ============================================================================ + +test-library: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "LIBRARY MODE: Testing Rust crate" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @# Test sync SDK with cargo test + @if [ -f "$(SYNC_DIR)/Cargo.toml" ]; then \ + cd $(SYNC_DIR) && cargo test 2>&1 | tail -20 || echo " $(YELLOW)⊘$(NC) Library: Sync tests incomplete"; \ + else \ + echo " $(YELLOW)⊘$(NC) Library: Sync SDK needs Cargo.toml"; \ + fi + @# Test async SDK with cargo test + @if [ -f "$(ASYNC_DIR)/Cargo.toml" ]; then \ + cd $(ASYNC_DIR) && cargo test 2>&1 | tail -20 || echo " $(YELLOW)⊘$(NC) Library: Async tests incomplete"; \ + fi + +# ============================================================================ +# TEST: Integration Mode +# ============================================================================ + +test-integration: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "INTEGRATION MODE: Testing API contract" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + echo " Set UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY"; \ + else \ + echo " Testing API authentication..."; \ + if [ -f "$(SYNC_DIR)/Cargo.toml" ]; then \ + cd $(SYNC_DIR) && cargo run --release -- -s python -c 'print(42)' 2>&1 | grep -q "42" && echo " $(GREEN)✓$(NC) Integration: API auth works" || echo " $(YELLOW)⊘$(NC) Integration: Check API connectivity"; \ + fi; \ + fi + +# ============================================================================ +# TEST: Functional Mode +# ============================================================================ + +test-functional: + @echo "" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "FUNCTIONAL MODE: Real-world scenarios" + @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + @echo "" + @if [ -z "$$UNSANDBOX_PUBLIC_KEY" ] || [ -z "$$UNSANDBOX_SECRET_KEY" ]; then \ + echo " $(YELLOW)⊘$(NC) Skipping (no API credentials)"; \ + else \ + echo " Running functional tests..."; \ + if [ -f "$(SYNC_DIR)/Cargo.toml" ]; then \ + cd $(SYNC_DIR) && cargo run --release -- -s python -c 'def fib(n): return n if n<2 else fib(n-1)+fib(n-2); print(fib(10))' 2>&1 | grep -q "55" && echo " $(GREEN)✓$(NC) Functional: Fibonacci" || echo " $(YELLOW)⊘$(NC) Functional: Fibonacci (check output)"; \ + fi; \ + fi + +# ============================================================================ +# TEST: By SDK Type +# ============================================================================ + +test-sync: + @echo "Testing Sync SDK..." + @if [ -f "$(SYNC_DIR)/Cargo.toml" ]; then \ + cd $(SYNC_DIR) && cargo test; \ + else \ + echo " $(YELLOW)⊘$(NC) Sync SDK not found"; \ + fi + +test-async: + @echo "Testing Async SDK..." + @if [ -f "$(ASYNC_DIR)/Cargo.toml" ]; then \ + cd $(ASYNC_DIR) && cargo test; \ + else \ + echo " $(YELLOW)⊘$(NC) Async SDK not found"; \ + fi + +# ============================================================================ +# Code Quality +# ============================================================================ + +fmt: + @echo "Formatting Rust code..." + @if [ -f "$(SYNC_DIR)/Cargo.toml" ]; then cd $(SYNC_DIR) && cargo fmt; fi + @if [ -f "$(ASYNC_DIR)/Cargo.toml" ]; then cd $(ASYNC_DIR) && cargo fmt; fi + @echo "$(GREEN)✓$(NC) Format complete" + +clippy: + @echo "Running clippy..." + @if [ -f "$(SYNC_DIR)/Cargo.toml" ]; then cd $(SYNC_DIR) && cargo clippy 2>&1 || true; fi + @if [ -f "$(ASYNC_DIR)/Cargo.toml" ]; then cd $(ASYNC_DIR) && cargo clippy 2>&1 || true; fi + @echo "$(GREEN)✓$(NC) Clippy complete" + +doc: + @echo "Generating documentation..." + @if [ -f "$(SYNC_DIR)/Cargo.toml" ]; then cd $(SYNC_DIR) && cargo doc --no-deps; fi + @if [ -f "$(ASYNC_DIR)/Cargo.toml" ]; then cd $(ASYNC_DIR) && cargo doc --no-deps; fi + @echo "$(GREEN)✓$(NC) Documentation generated" + +# ============================================================================ +# Examples +# ============================================================================ + +examples: + @echo "Running Rust examples..." + @if [ -d "$(SYNC_DIR)/examples" ] && [ -f "$(SYNC_DIR)/Cargo.toml" ]; then \ + cd $(SYNC_DIR) && for f in examples/*.rs; do \ + name=$$(basename "$$f" .rs); \ + echo "Running $$name..."; \ + cargo run --example "$$name" 2>&1 | head -10 || true; \ + done; \ + fi + +# ============================================================================ +# Clean +# ============================================================================ + +clean: + @echo "Cleaning Rust build artifacts..." + @if [ -d "$(SYNC_DIR)/target" ]; then rm -rf $(SYNC_DIR)/target; fi + @if [ -d "$(ASYNC_DIR)/target" ]; then rm -rf $(ASYNC_DIR)/target; fi + @echo "$(GREEN)✓$(NC) Cleaned build artifacts"