Unit tests for extension mapping, signature format, language detection, argument parsing, file operations, and API constants for: Systems: C, C++, Rust, Go, Zig, Nim, D, V, Crystal JVM: Java, Kotlin, Groovy, Clojure .NET: C#, F# Functional: Haskell, OCaml, Scheme, Common Lisp, Erlang, Elixir Scripting: Python, Ruby, JavaScript, TypeScript, Lua, Perl, PHP, Tcl, Bash, AWK, PowerShell Scientific: Julia, R, Fortran Legacy/Exotic: COBOL, Prolog, Forth, Raku, Objective-C, Dart All tests validate internal functions without API calls.
132 lines
4.5 KiB
Zig
132 lines
4.5 KiB
Zig
// Unit tests for un.zig - tests internal functions without API calls
|
|
// Run with: zig run test_zig.zig
|
|
|
|
const std = @import("std");
|
|
const mem = std.mem;
|
|
|
|
var passed: u32 = 0;
|
|
var failed: u32 = 0;
|
|
|
|
fn test_case(name: []const u8, result: bool) void {
|
|
if (result) {
|
|
std.debug.print(" ✓ {s}\n", .{name});
|
|
passed += 1;
|
|
} else {
|
|
std.debug.print(" ✗ {s}\n", .{name});
|
|
failed += 1;
|
|
}
|
|
}
|
|
|
|
fn getLanguage(ext: []const u8) ?[]const u8 {
|
|
const extensions = [_]struct { ext: []const u8, lang: []const u8 }{
|
|
.{ .ext = ".py", .lang = "python" },
|
|
.{ .ext = ".js", .lang = "javascript" },
|
|
.{ .ext = ".ts", .lang = "typescript" },
|
|
.{ .ext = ".rb", .lang = "ruby" },
|
|
.{ .ext = ".go", .lang = "go" },
|
|
.{ .ext = ".rs", .lang = "rust" },
|
|
.{ .ext = ".c", .lang = "c" },
|
|
.{ .ext = ".zig", .lang = "zig" },
|
|
.{ .ext = ".java", .lang = "java" },
|
|
};
|
|
|
|
for (extensions) |e| {
|
|
if (mem.eql(u8, ext, e.ext)) return e.lang;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
fn getExtension(filename: []const u8) []const u8 {
|
|
var i: usize = filename.len;
|
|
while (i > 0) : (i -= 1) {
|
|
if (filename[i - 1] == '.') return filename[i - 1 ..];
|
|
}
|
|
return "";
|
|
}
|
|
|
|
fn getBasename(path: []const u8) []const u8 {
|
|
var i: usize = path.len;
|
|
while (i > 0) : (i -= 1) {
|
|
if (path[i - 1] == '/') return path[i..];
|
|
}
|
|
return path;
|
|
}
|
|
|
|
fn startsWith(haystack: []const u8, needle: []const u8) bool {
|
|
if (needle.len > haystack.len) return false;
|
|
return mem.eql(u8, haystack[0..needle.len], needle);
|
|
}
|
|
|
|
fn contains(haystack: []const u8, needle: []const u8) bool {
|
|
return mem.indexOf(u8, haystack, needle) != null;
|
|
}
|
|
|
|
pub fn main() !void {
|
|
std.debug.print("\n=== Extension Mapping Tests ===\n", .{});
|
|
|
|
test_case("Python extension maps correctly", if (getLanguage(".py")) |l| mem.eql(u8, l, "python") else false);
|
|
|
|
test_case("Zig extension maps correctly", if (getLanguage(".zig")) |l| mem.eql(u8, l, "zig") else false);
|
|
|
|
test_case("JavaScript extension maps correctly", if (getLanguage(".js")) |l| mem.eql(u8, l, "javascript") else false);
|
|
|
|
test_case("Go extension maps correctly", if (getLanguage(".go")) |l| mem.eql(u8, l, "go") else false);
|
|
|
|
std.debug.print("\n=== Signature Format Tests ===\n", .{});
|
|
|
|
const timestamp = "1704067200";
|
|
const method = "POST";
|
|
const endpoint = "/execute";
|
|
const body = "{\"language\":\"python\"}";
|
|
|
|
var message_buf: [256]u8 = undefined;
|
|
const message = std.fmt.bufPrint(&message_buf, "{s}:{s}:{s}:{s}", .{ timestamp, method, endpoint, body }) catch "";
|
|
|
|
test_case("Signature format starts with timestamp", startsWith(message, timestamp));
|
|
|
|
test_case("Signature format contains :POST:", contains(message, ":POST:"));
|
|
|
|
test_case("Signature format contains :/execute:", contains(message, ":/execute:"));
|
|
|
|
std.debug.print("\n=== Language Detection Tests ===\n", .{});
|
|
|
|
const content = "#!/usr/bin/env python3\nprint('hello')";
|
|
const newline_idx = mem.indexOf(u8, content, "\n") orelse content.len;
|
|
const first_line = content[0..newline_idx];
|
|
|
|
test_case("Python shebang detection - starts with #!", startsWith(first_line, "#!"));
|
|
|
|
test_case("Python shebang detection - contains python", contains(first_line, "python"));
|
|
|
|
std.debug.print("\n=== Argument Parsing Tests ===\n", .{});
|
|
|
|
const arg1 = "DEBUG=1";
|
|
const eq1_idx = mem.indexOf(u8, arg1, "=") orelse 0;
|
|
const key1 = arg1[0..eq1_idx];
|
|
const value1 = arg1[eq1_idx + 1 ..];
|
|
|
|
test_case("Parse -e KEY=VALUE format - key", mem.eql(u8, key1, "DEBUG"));
|
|
|
|
test_case("Parse -e KEY=VALUE format - value", mem.eql(u8, value1, "1"));
|
|
|
|
std.debug.print("\n=== File Operations Tests ===\n", .{});
|
|
|
|
test_case("Extract file basename", mem.eql(u8, getBasename("/home/user/project/script.zig"), "script.zig"));
|
|
|
|
test_case("Extract file extension", mem.eql(u8, getExtension("/home/user/project/script.zig"), ".zig"));
|
|
|
|
std.debug.print("\n=== API Constants Tests ===\n", .{});
|
|
|
|
const api_base = "https://api.unsandbox.com";
|
|
|
|
test_case("API base URL starts with https://", startsWith(api_base, "https://"));
|
|
|
|
test_case("API base URL contains unsandbox.com", contains(api_base, "unsandbox.com"));
|
|
|
|
std.debug.print("\n=== Summary ===\n", .{});
|
|
std.debug.print("Passed: {d}\n", .{passed});
|
|
std.debug.print("Failed: {d}\n", .{failed});
|
|
std.debug.print("Total: {d}\n", .{passed + failed});
|
|
|
|
std.process.exit(if (failed > 0) 1 else 0);
|
|
}
|