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
213 lines
7 KiB
Zig
213 lines
7 KiB
Zig
// Tests for the Zig unsandbox SDK
|
|
// Run with: zig test tests/test_un.zig
|
|
|
|
const std = @import("std");
|
|
const un = @import("../src/un.zig");
|
|
const testing = std.testing;
|
|
const mem = std.mem;
|
|
|
|
// ============================================================================
|
|
// Unit Tests - Test exported library functions
|
|
// ============================================================================
|
|
|
|
test "detectLanguage" {
|
|
try testing.expectEqualStrings("python", un.detectLanguage("script.py") orelse "");
|
|
try testing.expectEqualStrings("javascript", un.detectLanguage("script.js") orelse "");
|
|
try testing.expectEqualStrings("typescript", un.detectLanguage("script.ts") orelse "");
|
|
try testing.expectEqualStrings("go", un.detectLanguage("script.go") orelse "");
|
|
try testing.expectEqualStrings("rust", un.detectLanguage("script.rs") orelse "");
|
|
try testing.expectEqualStrings("c", un.detectLanguage("script.c") orelse "");
|
|
try testing.expectEqualStrings("cpp", un.detectLanguage("script.cpp") orelse "");
|
|
try testing.expectEqualStrings("d", un.detectLanguage("script.d") orelse "");
|
|
try testing.expectEqualStrings("zig", un.detectLanguage("script.zig") orelse "");
|
|
try testing.expectEqualStrings("bash", un.detectLanguage("script.sh") orelse "");
|
|
try testing.expectEqualStrings("ruby", un.detectLanguage("script.rb") orelse "");
|
|
try testing.expectEqualStrings("php", un.detectLanguage("script.php") orelse "");
|
|
try testing.expect(un.detectLanguage("script.unknown") == null);
|
|
try testing.expect(un.detectLanguage("script") == null);
|
|
}
|
|
|
|
test "version" {
|
|
const v = un.version();
|
|
try testing.expect(v.len > 0);
|
|
// Should be in semver format (at least "0.0.0")
|
|
try testing.expect(v.len >= 5);
|
|
}
|
|
|
|
test "lastError" {
|
|
// Set an error
|
|
un.setLastError("test error message");
|
|
|
|
// Retrieve it
|
|
const err = un.lastError();
|
|
try testing.expectEqualStrings("test error message", err);
|
|
|
|
// Clear it
|
|
un.setLastError("");
|
|
const err2 = un.lastError();
|
|
try testing.expectEqualStrings("", err2);
|
|
}
|
|
|
|
test "SDK_VERSION constant" {
|
|
try testing.expect(un.SDK_VERSION.len > 0);
|
|
try testing.expect(un.SDK_VERSION.len >= 5);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Integration Tests - Test SDK internal consistency
|
|
// ============================================================================
|
|
|
|
test "hmacSign" {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
const secret_key = "test-secret";
|
|
const message = "test-message";
|
|
|
|
const result = try un.hmacSign(allocator, secret_key, message);
|
|
defer allocator.free(result);
|
|
|
|
// Should return a 64-character hex string
|
|
try testing.expectEqual(@as(usize, 64), result.len);
|
|
|
|
// Should be deterministic
|
|
const result2 = try un.hmacSign(allocator, secret_key, message);
|
|
defer allocator.free(result2);
|
|
try testing.expectEqualStrings(result, result2);
|
|
|
|
// Different inputs should produce different outputs
|
|
const result3 = try un.hmacSign(allocator, secret_key, "different-message");
|
|
defer allocator.free(result3);
|
|
try testing.expect(!mem.eql(u8, result, result3));
|
|
}
|
|
|
|
// ============================================================================
|
|
// Functional Tests - Test against real API (requires credentials)
|
|
// These tests are marked as skipped by default since they require credentials
|
|
// ============================================================================
|
|
|
|
fn hasCredentials() bool {
|
|
const pk = std.posix.getenv("UNSANDBOX_PUBLIC_KEY") orelse return false;
|
|
const sk = std.posix.getenv("UNSANDBOX_SECRET_KEY") orelse return false;
|
|
return pk.len > 0 and sk.len > 0;
|
|
}
|
|
|
|
fn getCredentials() ?struct { pk: []const u8, sk: []const u8 } {
|
|
const pk = std.posix.getenv("UNSANDBOX_PUBLIC_KEY") orelse return null;
|
|
const sk = std.posix.getenv("UNSANDBOX_SECRET_KEY") orelse return null;
|
|
if (pk.len == 0 or sk.len == 0) return null;
|
|
return .{ .pk = pk, .sk = sk };
|
|
}
|
|
|
|
test "healthCheck functional" {
|
|
if (!hasCredentials()) {
|
|
std.debug.print("SKIP (no credentials)\n", .{});
|
|
return;
|
|
}
|
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
const healthy = try un.healthCheck(allocator);
|
|
std.debug.print("Health check result: {}\n", .{healthy});
|
|
}
|
|
|
|
test "getLanguages functional" {
|
|
const creds = getCredentials() orelse {
|
|
std.debug.print("SKIP (no credentials)\n", .{});
|
|
return;
|
|
};
|
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
const result = try un.getLanguages(allocator, creds.pk, creds.sk);
|
|
defer allocator.free(result);
|
|
|
|
try testing.expect(result.len > 0);
|
|
// Should contain python
|
|
try testing.expect(mem.indexOf(u8, result, "python") != null);
|
|
}
|
|
|
|
test "validateKeys functional" {
|
|
const creds = getCredentials() orelse {
|
|
std.debug.print("SKIP (no credentials)\n", .{});
|
|
return;
|
|
};
|
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
const result = try un.validateKeys(allocator, creds.pk, creds.sk);
|
|
defer allocator.free(result);
|
|
|
|
try testing.expect(result.len > 0);
|
|
}
|
|
|
|
test "sessionList functional" {
|
|
const creds = getCredentials() orelse {
|
|
std.debug.print("SKIP (no credentials)\n", .{});
|
|
return;
|
|
};
|
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
const result = try un.sessionList(allocator, creds.pk, creds.sk);
|
|
defer allocator.free(result);
|
|
|
|
try testing.expect(result.len > 0);
|
|
}
|
|
|
|
test "serviceList functional" {
|
|
const creds = getCredentials() orelse {
|
|
std.debug.print("SKIP (no credentials)\n", .{});
|
|
return;
|
|
};
|
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
const result = try un.serviceList(allocator, creds.pk, creds.sk);
|
|
defer allocator.free(result);
|
|
|
|
try testing.expect(result.len > 0);
|
|
}
|
|
|
|
test "snapshotList functional" {
|
|
const creds = getCredentials() orelse {
|
|
std.debug.print("SKIP (no credentials)\n", .{});
|
|
return;
|
|
};
|
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
const result = try un.snapshotList(allocator, creds.pk, creds.sk);
|
|
defer allocator.free(result);
|
|
|
|
try testing.expect(result.len > 0);
|
|
}
|
|
|
|
test "imageList functional" {
|
|
const creds = getCredentials() orelse {
|
|
std.debug.print("SKIP (no credentials)\n", .{});
|
|
return;
|
|
};
|
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
const result = try un.imageList(allocator, null, creds.pk, creds.sk);
|
|
defer allocator.free(result);
|
|
|
|
try testing.expect(result.len > 0);
|
|
}
|