add functional tests for 7 major SDKs (Python, Go, JS, Ruby, PHP, Java, Rust)

Each test file covers 10 real API tests matching the C SDK reference:
health_check, validate_keys, get_languages, execute, execute_error,
session_list, session_lifecycle, service_list, snapshot_list, image_list.

All tests skip cleanly without credentials. No soft passes.
Updated all 7 Makefiles to run dedicated functional test files.
This commit is contained in:
russell@unturf.com 2026-02-26 22:04:21 -05:00
parent 8fae03d9fd
commit de8c816b27
14 changed files with 1046 additions and 11 deletions

View file

@ -204,8 +204,10 @@ test-functional: check-go
echo " $(YELLOW)$(NC) Skipping (no API credentials)"; \
else \
echo " Running functional tests..."; \
if [ -d "$(SYNC_DIR)/tests" ]; then \
cd $(SYNC_DIR) && $(GO) test -v -run TestFunctional ./tests/ 2>&1 || true; \
if [ -d "$(SYNC_DIR)/tests" ] && [ -d "$(SYNC_DIR)/src" ]; then \
cp $(SYNC_DIR)/tests/functional_test.go $(SYNC_DIR)/src/ 2>/dev/null; \
cd $(SYNC_DIR)/src && $(GO) test -v -run TestFunctional . 2>&1; \
rm -f $(SYNC_DIR)/src/functional_test.go; \
fi; \
fi

View file

@ -0,0 +1,181 @@
// This is free software for the public good of a permacomputer hosted at
// permacomputer.com, an always-on computer by the people, for the people.
// One which is durable, easy to repair, & distributed like tap water
// for machine learning intelligence.
//
// The permacomputer is community-owned infrastructure optimized around
// four values:
//
// TRUTH First principles, math & science, open source code freely distributed
// FREEDOM Voluntary partnerships, freedom from tyranny & corporate control
// HARMONY Minimal waste, self-renewing systems with diverse thriving connections
// LOVE Be yourself without hurting others, cooperation through natural law
//
// This software contributes to that vision by enabling code execution across 42+ programming languages through a unified interface, accessible to all.
// Code is seeds to sprout on any abandoned technology.
// UN Go SDK - Functional Tests
//
// Tests library functions against real API.
// Requires: UNSANDBOX_PUBLIC_KEY, UNSANDBOX_SECRET_KEY
//
// Usage:
// Copy to sync/src/ then: go test -v -run TestFunctional
package un
import (
"os"
"strings"
"testing"
)
func skipIfNoCreds(t *testing.T) *Credentials {
t.Helper()
pk := os.Getenv("UNSANDBOX_PUBLIC_KEY")
sk := os.Getenv("UNSANDBOX_SECRET_KEY")
if pk == "" || sk == "" {
t.Skip("UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY required")
}
return &Credentials{PublicKey: pk, SecretKey: sk}
}
func TestFunctionalHealthCheck(t *testing.T) {
_ = skipIfNoCreds(t)
result := HealthCheck()
// HealthCheck returns a bool - just verify it runs without panic
t.Logf("HealthCheck: %v", result)
}
func TestFunctionalValidateKeys(t *testing.T) {
creds := skipIfNoCreds(t)
info, err := ValidateKeys(creds)
if err != nil {
t.Fatalf("ValidateKeys error: %v", err)
}
if info == nil {
t.Fatal("ValidateKeys returned nil")
}
valid, ok := info["valid"]
if !ok {
t.Fatal("ValidateKeys result missing 'valid' key")
}
if valid != true {
t.Errorf("Keys should be valid, got: %v", valid)
}
}
func TestFunctionalGetLanguages(t *testing.T) {
creds := skipIfNoCreds(t)
langs, err := GetLanguages(creds)
if err != nil {
t.Fatalf("GetLanguages error: %v", err)
}
if len(langs) == 0 {
t.Fatal("GetLanguages returned empty list")
}
foundPython := false
for _, l := range langs {
if l == "python" {
foundPython = true
break
}
}
if !foundPython {
t.Error("python not found in languages list")
}
t.Logf("Found %d languages", len(langs))
}
func TestFunctionalExecute(t *testing.T) {
creds := skipIfNoCreds(t)
result, err := ExecuteCode(creds, "python", "print('hello from Go SDK')")
if err != nil {
t.Fatalf("ExecuteCode error: %v", err)
}
if result == nil {
t.Fatal("ExecuteCode returned nil")
}
stdout, _ := result["stdout"].(string)
if !strings.Contains(stdout, "hello from Go SDK") {
t.Errorf("stdout should contain 'hello from Go SDK', got: %s", stdout)
}
exitCode, _ := result["exit_code"].(float64)
if exitCode != 0 {
t.Errorf("exit_code should be 0, got: %v", exitCode)
}
}
func TestFunctionalExecuteError(t *testing.T) {
creds := skipIfNoCreds(t)
result, err := ExecuteCode(creds, "python", "import sys; sys.exit(1)")
if err != nil {
t.Fatalf("ExecuteCode error: %v", err)
}
if result == nil {
t.Fatal("ExecuteCode returned nil")
}
exitCode, _ := result["exit_code"].(float64)
if exitCode != 1 {
t.Errorf("exit_code should be 1, got: %v", exitCode)
}
}
func TestFunctionalSessionList(t *testing.T) {
creds := skipIfNoCreds(t)
sessions, err := ListSessions(creds)
if err != nil {
t.Fatalf("ListSessions error: %v", err)
}
t.Logf("Found %d sessions", len(sessions))
}
func TestFunctionalSessionLifecycle(t *testing.T) {
creds := skipIfNoCreds(t)
// Create
session, err := CreateSession(creds, nil)
if err != nil {
t.Fatalf("CreateSession error: %v", err)
}
if session == nil {
t.Fatal("CreateSession returned nil")
}
sessionID, _ := session["id"].(string)
if sessionID == "" {
t.Fatal("Session missing id")
}
t.Logf("Created session: %s", sessionID)
// Destroy
_, err = DeleteSession(creds, sessionID)
if err != nil {
t.Errorf("DeleteSession error: %v", err)
}
}
func TestFunctionalServiceList(t *testing.T) {
creds := skipIfNoCreds(t)
services, err := ListServices(creds)
if err != nil {
t.Fatalf("ListServices error: %v", err)
}
t.Logf("Found %d services", len(services))
}
func TestFunctionalSnapshotList(t *testing.T) {
creds := skipIfNoCreds(t)
snapshots, err := ListSnapshots(creds)
if err != nil {
t.Fatalf("ListSnapshots error: %v", err)
}
t.Logf("Found %d snapshots", len(snapshots))
}
func TestFunctionalImageList(t *testing.T) {
creds := skipIfNoCreds(t)
images, err := ListImages(creds, "")
if err != nil {
t.Fatalf("ListImages error: %v", err)
}
t.Logf("Found %d images", len(images))
}

View file

@ -196,7 +196,12 @@ test-functional:
echo " $(YELLOW)$(NC) Skipping (no API credentials)"; \
else \
echo " Running functional tests..."; \
echo " $(YELLOW)$(NC) Functional: SDK not yet implemented"; \
if [ -f "$(SYNC_DIR)/tests/TestFunctional.java" ] && [ -f "$(SYNC_DIR)/src/Un.java" ]; then \
$(JAVAC) -cp $(SYNC_DIR)/src $(SYNC_DIR)/tests/TestFunctional.java -d /tmp/un-java-test 2>&1 && \
$(JAVA) -cp /tmp/un-java-test:$(SYNC_DIR)/src TestFunctional 2>&1 && \
echo " $(GREEN)$(NC) Functional: All tests passed" || echo " $(RED)$(NC) Functional: Tests failed"; \
rm -rf /tmp/un-java-test; \
fi; \
fi
# ============================================================================

View file

@ -0,0 +1,186 @@
/**
* This is free software for the public good of a permacomputer hosted at
* permacomputer.com, an always-on computer by the people, for the people.
* One which is durable, easy to repair, & distributed like tap water
* for machine learning intelligence.
*
* The permacomputer is community-owned infrastructure optimized around
* four values:
*
* TRUTH First principles, math & science, open source code freely distributed
* FREEDOM Voluntary partnerships, freedom from tyranny & corporate control
* HARMONY Minimal waste, self-renewing systems with diverse thriving connections
* LOVE Be yourself without hurting others, cooperation through natural law
*
* This software contributes to that vision by enabling code execution across 42+ programming languages through a unified interface, accessible to all.
* Code is seeds to sprout on any abandoned technology.
*
* UN Java SDK - Functional Tests
*
* Tests library functions against real API.
* Requires: UNSANDBOX_PUBLIC_KEY, UNSANDBOX_SECRET_KEY
*
* Usage:
* javac -cp src tests/TestFunctional.java && java -cp src:tests TestFunctional
*/
import java.io.IOException;
import java.util.*;
public class TestFunctional {
private static int passed = 0;
private static int failed = 0;
private static final String GREEN = "\033[32m";
private static final String RED = "\033[31m";
private static final String NC = "\033[0m";
private static void check(boolean condition, String msg) {
if (condition) {
System.out.println(" " + GREEN + "" + NC + " " + msg);
passed++;
} else {
System.out.println(" " + RED + "" + NC + " " + msg);
failed++;
}
}
private static void testHealthCheck() {
System.out.println("\nTesting healthCheck()...");
boolean result = Un.healthCheck();
check(true, "healthCheck completed without exception");
}
private static void testValidateKeys() throws IOException {
System.out.println("\nTesting validateKeys()...");
Map<String, Object> info = Un.validateKeys(null, null);
check(info != null, "validateKeys returns non-null");
if (info != null) {
check(info.containsKey("valid"), "result has 'valid' key");
check(Boolean.TRUE.equals(info.get("valid")), "keys are valid");
Object tier = info.get("tier");
if (tier != null) System.out.println(" tier: " + tier);
}
}
private static void testGetLanguages() throws IOException {
System.out.println("\nTesting getLanguages()...");
List<String> langs = Un.getLanguages(null, null);
check(langs != null, "getLanguages returns non-null");
if (langs != null) {
check(!langs.isEmpty(), "at least one language returned");
check(langs.contains("python"), "python is in languages list");
System.out.println(" Found " + langs.size() + " languages");
}
}
private static void testExecute() throws IOException {
System.out.println("\nTesting executeCode()...");
Map<String, Object> result = Un.executeCode("python", "print('hello from Java SDK')", null, null);
check(result != null, "execute returns non-null");
if (result != null) {
String stdout = (String) result.get("stdout");
check(stdout != null && stdout.contains("hello from Java SDK"), "stdout contains expected output");
Object exitCode = result.get("exit_code");
check(exitCode != null && ((Number) exitCode).intValue() == 0, "exit code is 0");
}
}
private static void testExecuteError() throws IOException {
System.out.println("\nTesting executeCode() with error...");
Map<String, Object> result = Un.executeCode("python", "import sys; sys.exit(1)", null, null);
check(result != null, "execute returns non-null");
if (result != null) {
Object exitCode = result.get("exit_code");
check(exitCode != null && ((Number) exitCode).intValue() == 1, "exit code is 1");
}
}
private static void testSessionList() throws IOException {
System.out.println("\nTesting listSessions()...");
List<Map<String, Object>> sessions = Un.listSessions(null, null);
check(sessions != null, "listSessions returns non-null");
if (sessions != null) {
System.out.println(" Found " + sessions.size() + " sessions");
}
}
private static void testSessionLifecycle() throws IOException {
System.out.println("\nTesting session lifecycle (create, destroy)...");
Map<String, Object> session = Un.createSession("python", null, null, null);
check(session != null, "createSession returns non-null");
if (session != null) {
String sessionId = (String) session.get("id");
check(sessionId != null, "session has id");
System.out.println(" session_id: " + sessionId);
if (sessionId != null) {
Un.deleteSession(sessionId, null, null);
check(true, "deleteSession completed");
}
}
}
private static void testServiceList() throws IOException {
System.out.println("\nTesting listServices()...");
List<Map<String, Object>> services = Un.listServices(null, null);
check(services != null, "listServices returns non-null");
if (services != null) {
System.out.println(" Found " + services.size() + " services");
}
}
private static void testSnapshotList() throws IOException {
System.out.println("\nTesting listSnapshots()...");
List<Map<String, Object>> snapshots = Un.listSnapshots(null, null);
check(snapshots != null, "listSnapshots returns non-null");
if (snapshots != null) {
System.out.println(" Found " + snapshots.size() + " snapshots");
}
}
private static void testImageList() throws IOException {
System.out.println("\nTesting listImages()...");
List<Map<String, Object>> images = Un.listImages(null, null, null);
check(images != null, "listImages returns non-null");
if (images != null) {
System.out.println(" Found " + images.size() + " images");
}
}
public static void main(String[] args) {
System.out.println("=====================================");
System.out.println("UN Java SDK - Functional Tests");
System.out.println("Testing against real API");
System.out.println("=====================================");
String pk = System.getenv("UNSANDBOX_PUBLIC_KEY");
String sk = System.getenv("UNSANDBOX_SECRET_KEY");
if (pk == null || sk == null || pk.isEmpty() || sk.isEmpty()) {
System.out.println("\n\033[33mSKIP: UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY not set\033[0m");
System.exit(0);
}
try { testHealthCheck(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
try { testValidateKeys(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
try { testGetLanguages(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
try { testExecute(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
try { testExecuteError(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
try { testSessionList(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
try { testSessionLifecycle(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
try { testServiceList(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
try { testSnapshotList(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
try { testImageList(); } catch (Exception e) { System.out.println(" " + RED + "" + e.getMessage() + NC); failed++; }
System.out.println("\n=====================================");
System.out.println("Test Summary");
System.out.println("=====================================");
System.out.println("Passed: " + GREEN + passed + NC);
System.out.println("Failed: " + RED + failed + NC);
System.out.println("=====================================");
System.exit(failed > 0 ? 1 : 0);
}
}

View file

@ -157,8 +157,8 @@ test-functional:
echo " $(YELLOW)$(NC) Skipping (no API credentials)"; \
else \
echo " Running functional tests..."; \
if [ -f "$(SYNC_DIR)/src/un.js" ]; then \
node --input-type=module -e "const un = await import('./$(SYNC_DIR)/src/un.js'); const r = await un.executeCode('python', 'def fib(n): return n if n<2 else fib(n-1)+fib(n-2); print(fib(10))'); if(r.stdout && r.stdout.includes('55')) console.log(' ✓ Functional: Fibonacci'); else console.log(' ✗ Functional: Check output');" 2>/dev/null || echo " $(RED)$(NC) Functional: SDK error"; \
if [ -f "$(SYNC_DIR)/tests/test_functional.mjs" ]; then \
node $(SYNC_DIR)/tests/test_functional.mjs 2>&1 && echo " $(GREEN)$(NC) Functional: All tests passed" || echo " $(RED)$(NC) Functional: Tests failed"; \
fi; \
fi

View file

@ -0,0 +1,184 @@
// This is free software for the public good of a permacomputer hosted at
// permacomputer.com, an always-on computer by the people, for the people.
// One which is durable, easy to repair, & distributed like tap water
// for machine learning intelligence.
//
// The permacomputer is community-owned infrastructure optimized around
// four values:
//
// TRUTH First principles, math & science, open source code freely distributed
// FREEDOM Voluntary partnerships, freedom from tyranny & corporate control
// HARMONY Minimal waste, self-renewing systems with diverse thriving connections
// LOVE Be yourself without hurting others, cooperation through natural law
//
// This software contributes to that vision by enabling code execution across 42+ programming languages through a unified interface, accessible to all.
// Code is seeds to sprout on any abandoned technology.
/**
* UN JavaScript SDK - Functional Tests
*
* Tests library functions against real API.
* Requires: UNSANDBOX_PUBLIC_KEY, UNSANDBOX_SECRET_KEY
*
* Usage:
* node clients/javascript/sync/tests/test_functional.mjs
*/
import {
executeCode,
getLanguages,
listSessions,
createSession,
deleteSession,
listServices,
listSnapshots,
listImages,
validateKeys,
healthCheck,
} from '../src/un.js';
const GREEN = '\x1b[32m';
const RED = '\x1b[31m';
const BLUE = '\x1b[34m';
const YELLOW = '\x1b[33m';
const NC = '\x1b[0m';
let passed = 0;
let failed = 0;
function check(condition, msg) {
if (condition) {
console.log(` ${GREEN}${NC} ${msg}`);
passed++;
} else {
console.log(` ${RED}${NC} ${msg}`);
failed++;
}
}
async function testHealthCheck() {
console.log('\nTesting healthCheck()...');
const result = await healthCheck();
check(typeof result === 'boolean', 'healthCheck returns boolean');
}
async function testValidateKeys() {
console.log('\nTesting validateKeys()...');
const info = await validateKeys();
check(info != null, 'validateKeys returns non-null');
check(info.valid === true, 'keys are valid');
if (info.tier) console.log(` tier: ${info.tier}`);
}
async function testGetLanguages() {
console.log('\nTesting getLanguages()...');
const langs = await getLanguages();
check(Array.isArray(langs), 'getLanguages returns array');
check(langs.length > 0, 'at least one language returned');
check(langs.includes('python'), 'python is in languages list');
console.log(` Found ${langs.length} languages`);
}
async function testExecute() {
console.log('\nTesting executeCode()...');
const result = await executeCode('python', "print('hello from JS SDK')");
check(result != null, 'execute returns non-null');
check(result.stdout && result.stdout.includes('hello from JS SDK'), 'stdout contains expected output');
check(result.exit_code === 0, 'exit code is 0');
}
async function testExecuteError() {
console.log('\nTesting executeCode() with error...');
const result = await executeCode('python', 'import sys; sys.exit(1)');
check(result != null, 'execute returns non-null');
check(result.exit_code === 1, 'exit code is 1');
}
async function testSessionList() {
console.log('\nTesting listSessions()...');
const sessions = await listSessions();
check(Array.isArray(sessions), 'listSessions returns array');
console.log(` Found ${sessions.length} sessions`);
}
async function testSessionLifecycle() {
console.log('\nTesting session lifecycle (create, destroy)...');
const session = await createSession('python');
check(session != null, 'createSession returns non-null');
const sessionId = session.session_id || session.id;
check(sessionId != null, 'session has id');
console.log(` session_id: ${sessionId}`);
if (sessionId) {
const destroyed = await deleteSession(sessionId);
check(destroyed != null, 'deleteSession returns non-null');
}
}
async function testServiceList() {
console.log('\nTesting listServices()...');
const services = await listServices();
check(Array.isArray(services), 'listServices returns array');
console.log(` Found ${services.length} services`);
}
async function testSnapshotList() {
console.log('\nTesting listSnapshots()...');
const snapshots = await listSnapshots();
check(Array.isArray(snapshots), 'listSnapshots returns array');
console.log(` Found ${snapshots.length} snapshots`);
}
async function testImageList() {
console.log('\nTesting listImages()...');
const images = await listImages();
check(Array.isArray(images), 'listImages returns array');
console.log(` Found ${images.length} images`);
}
// Main
async function main() {
console.log('=====================================');
console.log('UN JavaScript SDK - Functional Tests');
console.log('Testing against real API');
console.log('=====================================');
if (!process.env.UNSANDBOX_PUBLIC_KEY || !process.env.UNSANDBOX_SECRET_KEY) {
console.log(`\n${YELLOW}SKIP: UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY not set${NC}`);
process.exit(0);
}
const tests = [
testHealthCheck,
testValidateKeys,
testGetLanguages,
testExecute,
testExecuteError,
testSessionList,
testSessionLifecycle,
testServiceList,
testSnapshotList,
testImageList,
];
for (const test of tests) {
try {
await test();
} catch (err) {
console.log(` ${RED}${NC} ${test.name}: ${err.message}`);
failed++;
}
}
console.log('\n=====================================');
console.log('Test Summary');
console.log('=====================================');
console.log(`Passed: ${GREEN}${passed}${NC}`);
console.log(`Failed: ${RED}${failed}${NC}`);
console.log('=====================================');
process.exit(failed > 0 ? 1 : 0);
}
main();

View file

@ -163,7 +163,9 @@ test-functional:
echo " $(YELLOW)$(NC) Skipping (no API credentials)"; \
else \
echo " Running functional tests..."; \
echo " $(YELLOW)$(NC) Functional: SDK not yet implemented"; \
if [ -f "$(SYNC_DIR)/tests/FunctionalTest.php" ]; then \
cd $(SYNC_DIR) && php vendor/bin/phpunit tests/FunctionalTest.php 2>&1 && echo " $(GREEN)$(NC) Functional: All tests passed" || echo " $(RED)$(NC) Functional: Tests failed"; \
fi; \
fi
# ============================================================================

View file

@ -0,0 +1,120 @@
<?php
/**
* This is free software for the public good of a permacomputer hosted at
* permacomputer.com, an always-on computer by the people, for the people.
* One which is durable, easy to repair, & distributed like tap water
* for machine learning intelligence.
*
* The permacomputer is community-owned infrastructure optimized around
* four values:
*
* TRUTH First principles, math & science, open source code freely distributed
* FREEDOM Voluntary partnerships, freedom from tyranny & corporate control
* HARMONY Minimal waste, self-renewing systems with diverse thriving connections
* LOVE Be yourself without hurting others, cooperation through natural law
*
* This software contributes to that vision by enabling code execution across 42+ programming languages through a unified interface, accessible to all.
* Code is seeds to sprout on any abandoned technology.
*
* UN PHP SDK - Functional Tests
*
* Tests library functions against real API.
* Requires: UNSANDBOX_PUBLIC_KEY, UNSANDBOX_SECRET_KEY
*
* Usage:
* cd clients/php/sync && phpunit tests/FunctionalTest.php
*/
declare(strict_types=1);
namespace Unsandbox\Tests;
use PHPUnit\Framework\TestCase;
require_once __DIR__ . '/../src/un.php';
use Unsandbox\Unsandbox;
class FunctionalTest extends TestCase
{
private Unsandbox $client;
protected function setUp(): void
{
if (empty(getenv('UNSANDBOX_PUBLIC_KEY')) || empty(getenv('UNSANDBOX_SECRET_KEY'))) {
$this->markTestSkipped('UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY required');
}
$this->client = new Unsandbox();
}
public function testHealthCheck(): void
{
$result = Unsandbox::healthCheck();
$this->assertIsBool($result);
}
public function testValidateKeys(): void
{
$info = $this->client->validateKeys();
$this->assertIsArray($info);
$this->assertArrayHasKey('valid', $info);
$this->assertTrue($info['valid']);
}
public function testGetLanguages(): void
{
$langs = $this->client->getLanguages();
$this->assertIsArray($langs);
$this->assertNotEmpty($langs);
$this->assertContains('python', $langs);
}
public function testExecute(): void
{
$result = $this->client->executeCode('python', "print('hello from PHP SDK')");
$this->assertIsArray($result);
$this->assertStringContainsString('hello from PHP SDK', $result['stdout'] ?? '');
$this->assertEquals(0, $result['exit_code'] ?? -1);
}
public function testExecuteError(): void
{
$result = $this->client->executeCode('python', 'import sys; sys.exit(1)');
$this->assertIsArray($result);
$this->assertEquals(1, $result['exit_code'] ?? -1);
}
public function testSessionList(): void
{
$sessions = $this->client->listSessions();
$this->assertIsArray($sessions);
}
public function testSessionLifecycle(): void
{
$session = $this->client->createSession('python');
$this->assertIsArray($session);
$this->assertArrayHasKey('id', $session);
$sessionId = $session['id'];
$this->client->deleteSession($sessionId);
}
public function testServiceList(): void
{
$services = $this->client->listServices();
$this->assertIsArray($services);
}
public function testSnapshotList(): void
{
$snapshots = $this->client->listSnapshots();
$this->assertIsArray($snapshots);
}
public function testImageList(): void
{
$images = $this->client->listImages();
$this->assertIsArray($images);
}
}

View file

@ -170,9 +170,7 @@ test-functional: $(VENV)/.deps-installed
echo " $(YELLOW)$(NC) Skipping (no API credentials)"; \
else \
echo " Running functional tests..."; \
if [ -f "$(SYNC_DIR)/verify_sdk.py" ]; then \
cd $(SYNC_DIR) && ../$(PYTHON) verify_sdk.py 2>/dev/null && echo " $(GREEN)$(NC) Functional: Sync SDK verified" || echo " $(RED)$(NC) Functional: Sync verification failed"; \
fi; \
cd $(SYNC_DIR) && PYTHONPATH=src ../$(PYTEST) tests/test_functional.py -v 2>&1 && echo " $(GREEN)$(NC) Functional: Sync SDK verified" || echo " $(RED)$(NC) Functional: Sync verification failed"; \
fi
# ============================================================================

View file

@ -0,0 +1,118 @@
# This is free software for the public good of a permacomputer hosted at
# permacomputer.com, an always-on computer by the people, for the people.
# One which is durable, easy to repair, & distributed like tap water
# for machine learning intelligence.
#
# The permacomputer is community-owned infrastructure optimized around
# four values:
#
# TRUTH First principles, math & science, open source code freely distributed
# FREEDOM Voluntary partnerships, freedom from tyranny & corporate control
# HARMONY Minimal waste, self-renewing systems with diverse thriving connections
# LOVE Be yourself without hurting others, cooperation through natural law
#
# This software contributes to that vision by enabling code execution across 42+ programming languages through a unified interface, accessible to all.
# Code is seeds to sprout on any abandoned technology.
"""
UN Python SDK - Functional Tests
Tests library functions against real API.
Requires: UNSANDBOX_PUBLIC_KEY, UNSANDBOX_SECRET_KEY
Usage:
cd clients/python/sync && PYTHONPATH=src pytest tests/test_functional.py -v
"""
import os
import sys
import pytest
# Import SDK functions
from un import (
execute_code,
get_languages,
list_sessions,
list_services,
list_snapshots,
list_images,
validate_keys,
health_check,
)
# Skip all tests if no credentials
pytestmark = pytest.mark.skipif(
not os.environ.get("UNSANDBOX_PUBLIC_KEY") or not os.environ.get("UNSANDBOX_SECRET_KEY"),
reason="UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY required",
)
class TestFunctional:
"""Functional tests against real API (matches C SDK test_functional.c)"""
def test_health_check(self):
"""API health check returns boolean"""
result = health_check()
assert isinstance(result, bool)
def test_validate_keys(self):
"""API keys validate successfully"""
info = validate_keys()
assert isinstance(info, dict)
assert "valid" in info
assert info["valid"] is True
def test_get_languages(self):
"""Languages endpoint returns list with python"""
langs = get_languages()
assert isinstance(langs, list)
assert len(langs) > 0
assert "python" in langs
def test_execute(self):
"""Execute python code and verify stdout"""
result = execute_code("python", "print('hello from Python SDK')")
assert isinstance(result, dict)
assert result.get("success") is True
assert "hello from Python SDK" in result.get("stdout", "")
assert result.get("exit_code") == 0
def test_execute_error(self):
"""Execute code that exits with error"""
result = execute_code("python", "import sys; sys.exit(1)")
assert isinstance(result, dict)
assert result.get("success") is False
assert result.get("exit_code") == 1
def test_session_list(self):
"""List sessions returns list"""
sessions = list_sessions()
assert isinstance(sessions, list)
def test_session_lifecycle(self):
"""Create and destroy a session"""
from un import create_session, delete_session
session = create_session("python")
assert isinstance(session, dict)
assert "id" in session
session_id = session["id"]
destroyed = delete_session(session_id)
assert destroyed is not None
def test_service_list(self):
"""List services returns list"""
services = list_services()
assert isinstance(services, list)
def test_snapshot_list(self):
"""List snapshots returns list"""
snapshots = list_snapshots()
assert isinstance(snapshots, list)
def test_image_list(self):
"""List images returns list"""
images = list_images()
assert isinstance(images, list)

View file

@ -162,7 +162,9 @@ test-functional:
echo " $(YELLOW)$(NC) Skipping (no API credentials)"; \
else \
echo " Running functional tests..."; \
echo " $(YELLOW)$(NC) Functional: SDK not yet implemented"; \
if [ -f "$(SYNC_DIR)/test/test_functional.rb" ]; then \
cd $(SYNC_DIR) && ruby test/test_functional.rb 2>&1 && echo " $(GREEN)$(NC) Functional: All tests passed" || echo " $(RED)$(NC) Functional: Tests failed"; \
fi; \
fi
# ============================================================================

View file

@ -0,0 +1,107 @@
# frozen_string_literal: true
# This is free software for the public good of a permacomputer hosted at
# permacomputer.com, an always-on computer by the people, for the people.
# One which is durable, easy to repair, & distributed like tap water
# for machine learning intelligence.
#
# The permacomputer is community-owned infrastructure optimized around
# four values:
#
# TRUTH First principles, math & science, open source code freely distributed
# FREEDOM Voluntary partnerships, freedom from tyranny & corporate control
# HARMONY Minimal waste, self-renewing systems with diverse thriving connections
# LOVE Be yourself without hurting others, cooperation through natural law
#
# This software contributes to that vision by enabling code execution across 42+ programming languages through a unified interface, accessible to all.
# Code is seeds to sprout on any abandoned technology.
# UN Ruby SDK - Functional Tests
#
# Tests library functions against real API.
# Requires: UNSANDBOX_PUBLIC_KEY, UNSANDBOX_SECRET_KEY
#
# Usage:
# cd clients/ruby/sync && ruby test/test_functional.rb
$LOAD_PATH.unshift File.expand_path('../src', __dir__)
require 'minitest/autorun'
require 'un'
class TestFunctional < Minitest::Test
def setup
skip 'UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY required' unless credentials?
end
def test_health_check
result = Un.health_check
assert [true, false].include?(result), 'health_check should return boolean'
end
def test_validate_keys
info = Un.validate_keys
assert_kind_of Hash, info
assert info.key?('valid') || info.key?(:valid), 'should have valid key'
assert_equal true, (info['valid'] || info[:valid])
end
def test_get_languages
langs = Un.get_languages
assert_kind_of Array, langs
refute_empty langs
assert_includes langs, 'python'
end
def test_execute
result = Un.execute_code('python', "print('hello from Ruby SDK')")
assert_kind_of Hash, result
stdout = result['stdout'] || result[:stdout] || ''
assert_includes stdout, 'hello from Ruby SDK'
exit_code = result['exit_code'] || result[:exit_code]
assert_equal 0, exit_code
end
def test_execute_error
result = Un.execute_code('python', 'import sys; sys.exit(1)')
assert_kind_of Hash, result
exit_code = result['exit_code'] || result[:exit_code]
assert_equal 1, exit_code
end
def test_session_list
sessions = Un.list_sessions
assert_kind_of Array, sessions
end
def test_session_lifecycle
session = Un.create_session('python')
assert_kind_of Hash, session
session_id = session['id'] || session[:id]
refute_nil session_id, 'session should have id'
Un.delete_session(session_id)
end
def test_service_list
services = Un.list_services
assert_kind_of Array, services
end
def test_snapshot_list
snapshots = Un.list_snapshots
assert_kind_of Array, snapshots
end
def test_image_list
images = Un.list_images
assert_kind_of Array, images
end
private
def credentials?
ENV['UNSANDBOX_PUBLIC_KEY'] && ENV['UNSANDBOX_SECRET_KEY'] &&
!ENV['UNSANDBOX_PUBLIC_KEY'].empty? && !ENV['UNSANDBOX_SECRET_KEY'].empty?
end
end

View file

@ -187,7 +187,7 @@ test-functional:
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)"; \
cd $(SYNC_DIR) && cargo test --test functional_test -- --nocapture 2>&1 && echo " $(GREEN)$(NC) Functional: All tests passed" || echo " $(RED)$(NC) Functional: Tests failed"; \
fi; \
fi

View file

@ -0,0 +1,130 @@
// This is free software for the public good of a permacomputer hosted at
// permacomputer.com, an always-on computer by the people, for the people.
// One which is durable, easy to repair, & distributed like tap water
// for machine learning intelligence.
//
// The permacomputer is community-owned infrastructure optimized around
// four values:
//
// TRUTH First principles, math & science, open source code freely distributed
// FREEDOM Voluntary partnerships, freedom from tyranny & corporate control
// HARMONY Minimal waste, self-renewing systems with diverse thriving connections
// LOVE Be yourself without hurting others, cooperation through natural law
//
// This software contributes to that vision by enabling code execution across 42+ programming languages through a unified interface, accessible to all.
// Code is seeds to sprout on any abandoned technology.
//! UN Rust SDK - Functional Tests
//!
//! Tests library functions against real API.
//! Requires: UNSANDBOX_PUBLIC_KEY, UNSANDBOX_SECRET_KEY
//!
//! Usage:
//! cd clients/rust/sync && cargo test --test functional_test
use un::*;
use std::env;
fn get_creds() -> Option<Credentials> {
let pk = env::var("UNSANDBOX_PUBLIC_KEY").ok()?;
let sk = env::var("UNSANDBOX_SECRET_KEY").ok()?;
if pk.is_empty() || sk.is_empty() {
return None;
}
Some(Credentials::new(pk, sk))
}
macro_rules! skip_no_creds {
() => {
match get_creds() {
Some(c) => c,
None => {
eprintln!("SKIP: UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY required");
return;
}
}
};
}
#[test]
fn functional_health_check() {
let _ = skip_no_creds!();
let result = health_check();
// Just verify it returns without panic
eprintln!("health_check: {}", result);
}
#[test]
fn functional_validate_keys() {
let creds = skip_no_creds!();
let info = validate_keys(&creds).expect("validate_keys should succeed");
assert!(info.valid, "keys should be valid");
}
#[test]
fn functional_get_languages() {
let creds = skip_no_creds!();
let langs = get_languages(&creds).expect("get_languages should succeed");
assert!(!langs.is_empty(), "should have at least one language");
assert!(langs.contains(&"python".to_string()), "python should be in languages list");
eprintln!("Found {} languages", langs.len());
}
#[test]
fn functional_execute() {
let creds = skip_no_creds!();
let result = execute_code("python", "print('hello from Rust SDK')", &creds)
.expect("execute should succeed");
assert!(result.stdout.contains("hello from Rust SDK"), "stdout should contain expected output");
assert_eq!(result.exit_code, 0, "exit code should be 0");
}
#[test]
fn functional_execute_error() {
let creds = skip_no_creds!();
let result = execute_code("python", "import sys; sys.exit(1)", &creds)
.expect("execute should return result even on error");
assert_eq!(result.exit_code, 1, "exit code should be 1");
}
#[test]
fn functional_session_list() {
let creds = skip_no_creds!();
let sessions = list_sessions(&creds).expect("list_sessions should succeed");
eprintln!("Found {} sessions", sessions.len());
}
#[test]
fn functional_session_lifecycle() {
let creds = skip_no_creds!();
// Create
let session = create_session("python", &creds, None)
.expect("create_session should succeed");
assert!(!session.id.is_empty(), "session should have id");
eprintln!("Created session: {}", session.id);
// Destroy
delete_session(&session.id, &creds).expect("delete_session should succeed");
}
#[test]
fn functional_service_list() {
let creds = skip_no_creds!();
let services = list_services(&creds).expect("list_services should succeed");
eprintln!("Found {} services", services.len());
}
#[test]
fn functional_snapshot_list() {
let creds = skip_no_creds!();
let snapshots = list_snapshots(&creds).expect("list_snapshots should succeed");
eprintln!("Found {} snapshots", snapshots.len());
}
#[test]
fn functional_image_list() {
let creds = skip_no_creds!();
let images = list_images(None, &creds).expect("list_images should succeed");
eprintln!("Found {} images", images.len());
}