un-inception/docs/INCEPTION-TESTING.md

14 KiB
Raw Permalink Blame History

The Inception Test Matrix

638 Tests. 42 Languages. 100% Pass Rate.

████████╗██╗  ██╗███████╗    ██╗███╗   ██╗ ██████╗███████╗██████╗ ████████╗██╗ ██████╗ ███╗   ██╗
╚══██╔══╝██║  ██║██╔════╝    ██║████╗  ██║██╔════╝██╔════╝██╔══██╗╚══██╔══╝██║██╔═══██╗████╗  ██║
   ██║   ███████║█████╗      ██║██╔██╗ ██║██║     █████╗  ██████╔╝   ██║   ██║██║   ██║██╔██╗ ██║
   ██║   ██╔══██║██╔══╝      ██║██║╚██╗██║██║     ██╔══╝  ██╔═══╝    ██║   ██║██║   ██║██║╚██╗██║
   ██║   ██║  ██║███████╗    ██║██║ ╚████║╚██████╗███████╗██║        ██║   ██║╚██████╔╝██║ ╚████║
   ╚═╝   ╚═╝  ╚═╝╚══════╝    ╚═╝╚═╝  ╚═══╝ ╚═════╝╚══════╝╚═╝        ╚═╝   ╚═╝ ╚═════╝ ╚═╝  ╚═══╝

We achieved comprehensive functional testing of the entire Unsandbox API across 42 programming languages - without installing a single compiler or interpreter locally.

The Insight

"Why install 42 compilers when the cloud already has them?"

The sandbox contains compilers and interpreters for all 42 supported languages. Instead of installing Python, Ruby, Go, Rust, Haskell, COBOL, and Fortran on our CI runners, we send code to the sandbox and let it execute.

This is inception: using the sandbox to test the sandbox.

The Pattern

┌──────────────────────────────────────────────────────────────────────────┐
│                              CI Runner                                    │
│                                                                          │
│   ┌──────────────┐                                                       │
│   │  build/un    │  ◄── Only this is compiled locally (C)                │
│   │  (C binary)  │                                                       │
│   └──────┬───────┘                                                       │
│          │                                                               │
│          │  HTTP Request: "Run this Go code"                             │
│          ▼                                                               │
│   ┌──────────────────────────────────────────────────────────────────┐  │
│   │                      UNSANDBOX API                                │  │
│   │  ┌────────────────────────────────────────────────────────────┐  │  │
│   │  │                   SANDBOX CONTAINER                         │  │  │
│   │  │                                                             │  │  │
│   │  │   ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐          │  │  │
│   │  │   │ Python  │ │   Go    │ │  Rust   │ │ Haskell │          │  │  │
│   │  │   │  3.11   │ │  1.21   │ │  1.75   │ │  9.4    │          │  │  │
│   │  │   └─────────┘ └─────────┘ └─────────┘ └─────────┘          │  │  │
│   │  │   ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐          │  │  │
│   │  │   │  Java   │ │ Kotlin  │ │  Swift  │ │   C#    │          │  │  │
│   │  │   │   21    │ │  1.9    │ │   5.9   │ │   12    │          │  │  │
│   │  │   └─────────┘ └─────────┘ └─────────┘ └─────────┘          │  │  │
│   │  │   ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐          │  │  │
│   │  │   │ FORTRAN │ │  COBOL  │ │  Forth  │ │ Prolog  │          │  │  │
│   │  │   │   95    │ │  GnuCOBOL│ │ gforth  │ │ SWI     │          │  │  │
│   │  │   └─────────┘ └─────────┘ └─────────┘ └─────────┘          │  │  │
│   │  │                                                             │  │  │
│   │  │              ... and 30 more languages                      │  │  │
│   │  └────────────────────────────────────────────────────────────┘  │  │
│   └──────────────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────────────┘

Test Coverage

Endpoints Tested

Endpoint Tests Description
Execute 5 Code execution with env vars, files, network
Languages 2 List languages, verify target exists
Sessions 2 List sessions, get info
Services 5 Full lifecycle: create, info, exec, logs, destroy
Snapshots 1 List snapshots
Images 1 List images
Key 1 Validate API credentials
SDK 2 File exists, runs in sandbox

Total: ~15 tests per language × 42 languages = 638 tests

Execute Endpoint Tests

# 1. Basic execution - language-specific hello world
build/un -s go 'package main; import "fmt"; func main() { fmt.Println("test-ok") }'

# 2. Environment variables
build/un -s python -e MY_VAR=secret 'import os; print(os.environ["MY_VAR"])'

# 3. File upload
build/un -s python -f data.csv 'import os; print(os.listdir("/tmp/input"))'

# 4. Network access
build/un -n semitrusted -s python 'import socket; print("network-ok")'

# 5. SDK inception
build/un -n semitrusted clients/python/sync/src/un.py

Service Lifecycle Tests

# Create service
build/un service --name test-app --bootstrap "echo started"
# → unsb-service-abc123

# Get info
build/un service --info unsb-service-abc123

# Execute command
build/un service --execute unsb-service-abc123 'echo hello'

# Get logs
build/un service --logs unsb-service-abc123

# Destroy
build/un service --destroy unsb-service-abc123

The 42 Languages

Interpreted (23)

Language File Hello World
Python un.py print("test-ok")
JavaScript un.js console.log("test-ok")
TypeScript un.ts console.log("test-ok")
Ruby un.rb puts "test-ok"
PHP un.php <?php echo "test-ok";
Perl un.pl print "test-ok\n";
Lua un.lua print("test-ok")
Bash un.sh echo "test-ok"
R un.r cat("test-ok\n")
AWK un.awk BEGIN { print "test-ok" }
Tcl un.tcl puts "test-ok"
Scheme un.scm (display "test-ok") (newline)
Common Lisp un.lisp (format t "test-ok~%")
Clojure un.clj (println "test-ok")
Elixir un.ex IO.puts "test-ok"
Erlang un.erl io:format("test-ok~n").
Groovy un.groovy println "test-ok"
Raku un.raku print "test-ok\n";
Julia un.jl println("test-ok")
Prolog un.pro :- write("test-ok"), nl, halt.
Forth un.forth .( test-ok) cr bye
PowerShell un.ps1 Write-Output "test-ok"
Deno un.ts console.log("test-ok")

Compiled (19)

Language File Hello World
Go un.go package main; import "fmt"; func main() { fmt.Println("test-ok") }
Rust lib.rs fn main() { println!("test-ok"); }
C un.c #include <stdio.h>\nint main() { printf("test-ok\n"); }
C++ un.cpp #include <iostream>\nint main() { std::cout << "test-ok"; }
Java Un.java public class Main { public static void main(String[] a) { System.out.println("test-ok"); } }
Kotlin un.kt fun main() { println("test-ok") }
Swift un.swift print("test-ok")
C# Un.cs System.Console.WriteLine("test-ok");
F# un.fs printfn "test-ok"
Haskell un.hs main = putStrLn "test-ok"
OCaml un.ml print_endline "test-ok"
D un.d import std.stdio; void main() { writeln("test-ok"); }
Nim un.nim echo "test-ok"
Zig un.zig std.debug.print("test-ok\n", .{});
Crystal un.cr puts "test-ok"
Fortran un.f90 program main; print *, 'test-ok'; end program
COBOL un.cob DISPLAY "test-ok". STOP RUN.
Objective-C un.m NSLog(@"test-ok");
V un.v fn main() { println("test-ok") }
Dart un.dart void main() { print("test-ok"); }

CI Architecture

# .gitlab-ci.yml
stages:
  - detect      # What changed?
  - generate    # Build test matrix
  - trigger     # Launch child pipeline

detect-changes:
  script: bash scripts/detect-changes.sh
  artifacts:
    paths: [changes.json]

generate-matrix:
  script: bash scripts/generate-matrix.sh
  artifacts:
    paths: [test-matrix.yml]

trigger-tests:
  trigger:
    include:
      - artifact: test-matrix.yml
        job: generate-matrix
# test-matrix.yml (generated)
test:
  parallel:
    matrix:
      - SDK_LANG: python
      - SDK_LANG: javascript
      - SDK_LANG: ruby
      - SDK_LANG: go
      - SDK_LANG: rust
      # ... 37 more languages
  script:
    - bash scripts/test-sdk.sh "$SDK_LANG"

Results

┌────────────────────────────────────────────────────────┐
│                                                        │
│   ███████╗███████╗ ██████╗                            │
│   ██╔════╝██╔════╝██╔═████╗                           │
│   ███████╗███████╗██║██╔██║                           │
│   ██╔════╝╚════██║████╔╝██║                           │
│   ██║     ███████║╚██████╔╝                           │
│   ╚═╝     ╚══════╝ ╚═════╝                            │
│                                                        │
│   TESTS PASSED                                         │
│                                                        │
├────────────────────────────────────────────────────────┤
│                                                        │
│   Total Tests:     638                                 │
│   Passed:          638                                 │
│   Failed:          0                                   │
│   Skipped:         0                                   │
│   Pass Rate:       100%                                │
│                                                        │
│   Languages:       42                                  │
│   Tests/Language:  ~15                                 │
│   Endpoints:       8                                   │
│                                                        │
└────────────────────────────────────────────────────────┘

Running Locally

# 1. Build the C CLI
bash scripts/build-clients.sh

# 2. Set credentials
export UNSANDBOX_PUBLIC_KEY="unsb-pk-xxxx"
export UNSANDBOX_SECRET_KEY="unsb-sk-xxxx"

# 3. Run tests for any language
bash scripts/test-sdk.sh python
bash scripts/test-sdk.sh rust
bash scripts/test-sdk.sh haskell
bash scripts/test-sdk.sh cobol
bash scripts/test-sdk.sh fortran

# 4. Run all languages
for lang in $(build/un languages); do
    bash scripts/test-sdk.sh "$lang"
done

Key Files

File Lines Purpose
scripts/test-sdk.sh 430 Main test runner
scripts/generate-matrix.sh 100 Dynamic CI matrix
scripts/detect-changes.sh 80 Smart change detection
scripts/build-clients.sh 50 Builds C CLI

The Philosophy

The inception pattern proves that:

  1. Zero Setup is Possible: You don't need 42 compilers locally
  2. The Cloud is the Environment: Test in the same place you deploy
  3. Languages are Just Strings: build/un -s fortran 'print *, "hello"'
  4. Complexity Hides Behind Simplicity: One CLI, infinite languages

42 languages. 638 tests. 100% pass rate.

The inception is complete.