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

@ -6,6 +6,7 @@
* - HMAC-SHA256 signature generation
* - Credential resolution logic
* - Language detection
* - Utility functions
*
* To run tests:
* mvn test
@ -80,6 +81,18 @@ public class UnTest {
assertEquals("cpp", Un.detectLanguage("main.cxx"));
}
@Test
@DisplayName("Should detect Kotlin from .kt extension")
void detectKotlin() {
assertEquals("kotlin", Un.detectLanguage("Main.kt"));
}
@Test
@DisplayName("Should detect Groovy from .groovy extension")
void detectGroovy() {
assertEquals("groovy", Un.detectLanguage("script.groovy"));
}
@Test
@DisplayName("Should return null for unknown extension")
void detectUnknown() {
@ -94,6 +107,44 @@ public class UnTest {
}
}
@Nested
@DisplayName("Utility Function Tests")
class UtilityTests {
@Test
@DisplayName("Version should return a valid version string")
void versionString() {
String version = Un.version();
assertNotNull(version);
assertTrue(version.matches("\\d+\\.\\d+\\.\\d+"), "Version should be in X.Y.Z format");
}
@Test
@DisplayName("HMAC sign should produce valid hex signature")
void hmacSignature() {
String signature = Un.hmacSign("secret", "message");
assertNotNull(signature);
assertEquals(64, signature.length(), "HMAC-SHA256 should produce 64 hex chars");
assertTrue(signature.matches("[0-9a-f]+"), "Signature should be lowercase hex");
}
@Test
@DisplayName("HMAC sign should be consistent")
void hmacConsistent() {
String sig1 = Un.hmacSign("key", "data");
String sig2 = Un.hmacSign("key", "data");
assertEquals(sig1, sig2, "Same inputs should produce same signature");
}
@Test
@DisplayName("HMAC sign should differ with different inputs")
void hmacDifferent() {
String sig1 = Un.hmacSign("key1", "data");
String sig2 = Un.hmacSign("key2", "data");
assertNotEquals(sig1, sig2, "Different keys should produce different signatures");
}
}
@Nested
@DisplayName("Credential Exception Tests")
class CredentialExceptionTests {
@ -120,6 +171,22 @@ public class UnTest {
}
}
@Nested
@DisplayName("Sudo Challenge Exception Tests")
class SudoChallengeExceptionTests {
@Test
@DisplayName("SudoChallengeException should contain challenge ID")
void sudoChallengeDetails() {
Un.SudoChallengeException ex = new Un.SudoChallengeException(
"challenge-123",
"{\"challenge_id\": \"challenge-123\"}"
);
assertEquals("challenge-123", ex.getChallengeId());
assertEquals("{\"challenge_id\": \"challenge-123\"}", ex.getResponseBody());
}
}
@Nested
@DisplayName("Integration Tests (requires credentials)")
@EnabledIfEnvironmentVariable(named = "UNSANDBOX_PUBLIC_KEY", matches = ".+")
@ -193,5 +260,63 @@ public class UnTest {
assertEquals("completed", result.get("status"));
assertTrue(result.get("stdout").toString().contains("Async test"));
}
@Test
@DisplayName("Should list jobs")
void listJobs() throws IOException {
List<Map<String, Object>> jobs = Un.listJobs(publicKey, secretKey);
assertNotNull(jobs);
// Jobs list can be empty if no jobs are running
}
@Test
@DisplayName("Should validate keys successfully")
void validateKeys() throws IOException {
Map<String, Object> result = Un.validateKeys(publicKey, secretKey);
assertNotNull(result);
// The response should contain validation info
}
@Test
@DisplayName("Should list sessions")
void listSessions() throws IOException {
List<Map<String, Object>> sessions = Un.listSessions(publicKey, secretKey);
assertNotNull(sessions);
}
@Test
@DisplayName("Should list services")
void listServices() throws IOException {
List<Map<String, Object>> services = Un.listServices(publicKey, secretKey);
assertNotNull(services);
}
@Test
@DisplayName("Should list snapshots")
void listSnapshots() throws IOException {
List<Map<String, Object>> snapshots = Un.listSnapshots(publicKey, secretKey);
assertNotNull(snapshots);
}
@Test
@DisplayName("Should list images")
void listImages() throws IOException {
List<Map<String, Object>> images = Un.listImages(null, publicKey, secretKey);
assertNotNull(images);
}
}
@Nested
@DisplayName("Health Check Tests")
class HealthCheckTests {
@Test
@DisplayName("Health check should return boolean")
void healthCheckReturnsBoolean() {
boolean healthy = Un.healthCheck();
// We just verify it returns without throwing
// The actual result depends on network connectivity
assertTrue(healthy || !healthy);
}
}
}