feat: full feature parity for all 42 SDKs + comprehensive tests

All SDKs now implement 58+ functions matching C reference (un.h):
- Execution (8): execute, execute_async, wait_job, get_job, cancel_job, list_jobs, get_languages, detect_language
- Sessions (9): list, get, create, destroy, freeze, unfreeze, boost, unboost, execute
- Services (17): list, get, create, destroy, freeze, unfreeze, lock, unlock, set_unfreeze_on_demand, redeploy, logs, execute, env_get/set/delete/export, resize
- Snapshots (9): list, get, session, service, restore, delete, lock, unlock, clone
- Images (13): list, get, publish, delete, lock, unlock, set_visibility, grant/revoke_access, list_trusted, transfer, spawn, clone
- PaaS Logs (2): fetch, stream
- Utilities (5): validate_keys, hmac_sign, health_check, version, last_error

Test suites created for all SDKs with unit, integration, and functional tests.

Languages: AWK, Bash, C++, C#, Clojure, COBOL, Crystal, D, Dart, .NET, Elixir, Erlang, F#, Forth, Fortran, Go, Groovy, Haskell, Java, JavaScript, Julia, Kotlin, Lisp, Lua, Nim, Objective-C, OCaml, Perl, PHP, PowerShell, Prolog, Python, R, Raku, Ruby, Rust, Scheme, Swift, Tcl, TypeScript, V, Zig
This commit is contained in:
russell@unturf.com 2026-02-05 16:45:02 -05:00
parent a5155aed4f
commit 6e746ace44
90 changed files with 28955 additions and 3028 deletions

View file

@ -757,6 +757,97 @@ function Invoke-Image {
exit 1
}
function Invoke-Snapshot {
param($Args)
# Parse arguments
$listMode = $Args -contains "--list" -or $Args -contains "-l"
$infoId = $null
$deleteId = $null
$lockId = $null
$unlockId = $null
$restoreId = $null
$cloneId = $null
$cloneType = $null
$name = $null
$shell = $null
$ports = $null
for ($i = 0; $i -lt $Args.Count; $i++) {
switch ($Args[$i]) {
"--info" { $infoId = $Args[$i + 1]; $i++ }
"--delete" { $deleteId = $Args[$i + 1]; $i++ }
"--lock" { $lockId = $Args[$i + 1]; $i++ }
"--unlock" { $unlockId = $Args[$i + 1]; $i++ }
"--restore" { $restoreId = $Args[$i + 1]; $i++ }
"--clone" { $cloneId = $Args[$i + 1]; $i++ }
"--type" { $cloneType = $Args[$i + 1]; $i++ }
"--name" { $name = $Args[$i + 1]; $i++ }
"--shell" { $shell = $Args[$i + 1]; $i++ }
"-s" { $shell = $Args[$i + 1]; $i++ }
"--ports" { $ports = $Args[$i + 1]; $i++ }
}
}
if ($listMode) {
$result = Invoke-Api -Endpoint "/snapshots"
$result | ConvertTo-Json -Depth 5
return
}
if ($infoId) {
$result = Invoke-Api -Endpoint "/snapshots/$infoId"
$result | ConvertTo-Json -Depth 5
return
}
if ($deleteId) {
Invoke-ApiWithSudo -Endpoint "/snapshots/$deleteId" -Method "DELETE"
Write-Host "`e[32mSnapshot deleted: $deleteId`e[0m"
return
}
if ($lockId) {
Invoke-Api -Endpoint "/snapshots/$lockId/lock" -Method "POST" -Body "{}"
Write-Host "`e[32mSnapshot locked: $lockId`e[0m"
return
}
if ($unlockId) {
Invoke-ApiWithSudo -Endpoint "/snapshots/$unlockId/unlock" -Method "POST" -Body "{}"
Write-Host "`e[32mSnapshot unlocked: $unlockId`e[0m"
return
}
if ($restoreId) {
$result = Invoke-Api -Endpoint "/snapshots/$restoreId/restore" -Method "POST" -Body "{}"
Write-Host "`e[32mRestored from snapshot`e[0m"
$result | ConvertTo-Json -Depth 5
return
}
if ($cloneId) {
if (-not $cloneType) {
$cloneType = "session"
}
$payload = @{ type = $cloneType }
if ($name) { $payload["name"] = $name }
if ($shell) { $payload["shell"] = $shell }
if ($ports) {
$portList = $ports -split "," | ForEach-Object { [int]$_ }
$payload["ports"] = $portList
}
$body = $payload | ConvertTo-Json
$result = Invoke-Api -Endpoint "/snapshots/$cloneId/clone" -Method "POST" -Body $body
Write-Host "`e[32mCloned to $cloneType`e[0m"
$result | ConvertTo-Json -Depth 5
return
}
Write-Error "Error: Use --list, --info, --delete, --lock, --unlock, --restore, or --clone"
exit 1
}
function Invoke-Service {
param($Args)
@ -1011,6 +1102,7 @@ if ($args.Count -eq 0 -or $args[0] -eq "--help" -or $args[0] -eq "-h") {
Usage: pwsh un.ps1 [options] <source_file>
pwsh un.ps1 session [options]
pwsh un.ps1 service [options]
pwsh un.ps1 snapshot [options]
pwsh un.ps1 image [options]
pwsh un.ps1 languages [--json]
pwsh un.ps1 key [options]
@ -1068,6 +1160,19 @@ Service env commands:
env export ID Export vault contents
env delete ID Delete vault
Snapshot options:
--list, -l List all snapshots
--info ID Get snapshot details
--delete ID Delete snapshot
--lock ID Lock snapshot
--unlock ID Unlock snapshot
--restore ID Restore from snapshot
--clone ID Clone snapshot to session/service
--type TYPE Clone type: session or service
--name NAME Name for cloned resource
--shell NAME Shell for cloned session
--ports PORTS Ports for cloned service
Key options:
--extend Open browser to extend key
"@
@ -1078,6 +1183,8 @@ if ($args[0] -eq "session") {
Invoke-Session -Args $args[1..($args.Count-1)]
} elseif ($args[0] -eq "service") {
Invoke-Service -Args $args[1..($args.Count-1)]
} elseif ($args[0] -eq "snapshot") {
Invoke-Snapshot -Args $args[1..($args.Count-1)]
} elseif ($args[0] -eq "image") {
Invoke-Image -Args $args[1..($args.Count-1)]
} elseif ($args[0] -eq "languages") {

View file

@ -0,0 +1,162 @@
#!/usr/bin/env pwsh
# PUBLIC DOMAIN - NO LICENSE, NO WARRANTY
# Unit and Functional Tests for Unsandbox PowerShell SDK
$ErrorActionPreference = "Stop"
# Source the main script to get access to functions
. "$PSScriptRoot/../sync/src/un.ps1"
function Write-TestResult {
param($Name, $Passed, $Message = "")
if ($Passed) {
Write-Host " [PASS] $Name" -ForegroundColor Green
} else {
Write-Host " [FAIL] $Name $Message" -ForegroundColor Red
}
}
function Test-Unit {
Write-Host ""
Write-Host "=== PowerShell SDK Unit Tests ===" -ForegroundColor Cyan
Write-Host ""
# Test extension map
Write-Host "Testing extension detection..."
$tests = @{
".py" = "python"
".js" = "javascript"
".go" = "go"
".rs" = "rust"
".ps1" = "powershell"
}
$passed = 0
foreach ($ext in $tests.Keys) {
$expected = $tests[$ext]
$actual = $EXT_MAP[$ext]
if ($actual -eq $expected) {
$passed++
}
}
Write-TestResult "ExtensionMap" ($passed -eq $tests.Count) "($passed/$($tests.Count))"
# Test HMAC signing
Write-Host "Testing HMAC signing..."
$hmac = New-Object System.Security.Cryptography.HMACSHA256
$hmac.Key = [System.Text.Encoding]::UTF8.GetBytes("key")
$hash = $hmac.ComputeHash([System.Text.Encoding]::UTF8.GetBytes("message"))
$signature = [System.BitConverter]::ToString($hash).Replace("-", "").ToLower()
$expected = "6e9ef29b75fffc5b7abae527d58fdadb2fe42e7219011976917343065f58ed4a"
Write-TestResult "HmacSign" ($signature -eq $expected)
# Test env content building
Write-Host "Testing env content building..."
$envs = @("KEY1=value1", "KEY2=value2")
$result = Build-EnvContent -Envs $envs -EnvFile $null
$hasKey1 = $result -match "KEY1=value1"
$hasKey2 = $result -match "KEY2=value2"
Write-TestResult "BuildEnvContent" ($hasKey1 -and $hasKey2)
}
function Test-Functional {
Write-Host ""
Write-Host "=== PowerShell SDK Functional Tests ===" -ForegroundColor Cyan
Write-Host ""
$publicKey = $env:UNSANDBOX_PUBLIC_KEY
$secretKey = $env:UNSANDBOX_SECRET_KEY
if (-not $publicKey -or -not $secretKey) {
Write-Host " [SKIP] No API credentials (set UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY)" -ForegroundColor Yellow
return
}
# Test key validation
Write-Host "Testing key validation..."
try {
$result = Invoke-Api -Endpoint "/keys/validate" -Method "POST" -BaseUrl $PORTAL_BASE
Write-TestResult "ValidateKeys" ($null -ne $result)
} catch {
Write-TestResult "ValidateKeys" $false $_.Exception.Message
}
# Test languages endpoint
Write-Host "Testing languages endpoint..."
try {
$result = Invoke-Api -Endpoint "/languages"
$hasLanguages = ($result.languages -and $result.languages.Count -gt 0)
Write-TestResult "GetLanguages" $hasLanguages "($($result.languages.Count) languages)"
} catch {
Write-TestResult "GetLanguages" $false $_.Exception.Message
}
# Test execute
Write-Host "Testing execute endpoint..."
try {
$payload = @{
language = "python"
code = 'print("hello from powershell test")'
} | ConvertTo-Json
$result = Invoke-Api -Endpoint "/execute" -Method "POST" -Body $payload
$hasOutput = $result.stdout -match "hello"
Write-TestResult "Execute" $hasOutput
} catch {
Write-TestResult "Execute" $false $_.Exception.Message
}
# Test session list
Write-Host "Testing session list..."
try {
$result = Invoke-Api -Endpoint "/sessions"
Write-TestResult "SessionList" ($null -ne $result)
} catch {
Write-TestResult "SessionList" $false $_.Exception.Message
}
# Test service list
Write-Host "Testing service list..."
try {
$result = Invoke-Api -Endpoint "/services"
Write-TestResult "ServiceList" ($null -ne $result)
} catch {
Write-TestResult "ServiceList" $false $_.Exception.Message
}
# Test snapshot list
Write-Host "Testing snapshot list..."
try {
$result = Invoke-Api -Endpoint "/snapshots"
Write-TestResult "SnapshotList" ($null -ne $result)
} catch {
Write-TestResult "SnapshotList" $false $_.Exception.Message
}
# Test image list
Write-Host "Testing image list..."
try {
$result = Invoke-Api -Endpoint "/images"
Write-TestResult "ImageList" ($null -ne $result)
} catch {
Write-TestResult "ImageList" $false $_.Exception.Message
}
# Test snapshot list
Write-Host "Testing snapshot list..."
try {
$result = Invoke-Api -Endpoint "/snapshots"
Write-TestResult "SnapshotList" ($null -ne $result)
} catch {
Write-TestResult "SnapshotList" $false $_.Exception.Message
}
}
# Main
Write-Host "Unsandbox PowerShell SDK Tests" -ForegroundColor Cyan
Write-Host "==============================" -ForegroundColor Cyan
Test-Unit
Test-Functional
Write-Host ""
Write-Host "Tests complete." -ForegroundColor Cyan