From 64c1a1604df839a53b77ea52f119dc76a310651a Mon Sep 17 00:00:00 2001 From: torque Date: Sun, 27 Aug 2023 14:50:44 -0700 Subject: [PATCH] tests: add top level function tests These are mostly just tests to make sure the wrappers function as written, rather than testing for any specific output. This commit demonstrates the simple value of actually referencing the various wrapper functions, as a variety of really basic compilation errors were caught and addressed. --- src/error.zig | 6 ++-- src/nats.zig | 59 ++++++++++++++++++------------- tests/main.zig | 3 +- tests/nats.zig | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 30 deletions(-) create mode 100644 tests/nats.zig diff --git a/src/error.zig b/src/error.zig index 1290900..2ad8c58 100644 --- a/src/error.zig +++ b/src/error.zig @@ -12,7 +12,7 @@ pub const ErrorInfo = struct { }; pub fn getLastError() ErrorInfo { - const status: c_uint = 0; + var status: c_uint = 0; const desc = nats_c.nats_GetLastError(&status); return .{ @@ -21,8 +21,8 @@ pub fn getLastError() ErrorInfo { }; } -pub fn getLastErrorStack(buffer: []u8) Error!void { - const status = Status.fromInt(nats_c.getLastErrorStack(buffer.ptr, buffer.len)); +pub fn getLastErrorStack(buffer: *[]u8) Error!void { + const status = Status.fromInt(nats_c.nats_GetLastErrorStack(buffer.ptr, buffer.len)); return status.raise(); } diff --git a/src/nats.zig b/src/nats.zig index bf494c9..aefd67d 100644 --- a/src/nats.zig +++ b/src/nats.zig @@ -35,6 +35,9 @@ pub const Message = msg_.Message; pub const Statistics = sta_.Statistics; pub const StatsCounts = sta_.StatsCounts; +pub const ErrorInfo = err_.ErrorInfo; +pub const getLastError = err_.getLastError; +pub const getLastErrorStack = err_.getLastErrorStack; pub const Status = err_.Status; pub const Error = err_.Error; @@ -59,7 +62,7 @@ pub fn now() i64 { return nats_c.nats_Now(); } -pub fn nowInNanoSeconds() i64 { +pub fn nowInNanoseconds() i64 { return nats_c.nats_NowInNanoSeconds(); } @@ -76,6 +79,8 @@ pub fn releaseThreadMemory() void { return nats_c.nats_ReleaseThreadMemory(); } +pub const default_spin_count: i64 = -1; + pub fn init(lock_spin_count: i64) Error!void { const status = Status.fromInt(nats_c.nats_Open(lock_spin_count)); return status.raise(); @@ -85,37 +90,41 @@ pub fn deinit() void { return nats_c.nats_Close(); } -// the result of this requires manual deallocation unless it is used to provide the -// signature out-parameter in the natsSignatureHandler callback. Calling it outside of -// that context seems unlikely, but we should probably provide a deinit function so the -// user doesn't have to dig around for libc free to deallocate it. -pub fn sign(encoded_seed: [:0]const u8, input: [:0]const u8) Error![]const u8 { - var result: [*]u8 = undefined; - var length: c_int = 0; - const status = Status.fromInt(nats_c.nats_Sign(encoded_seed.ptr, &input, &length)); - - return status.toError() orelse result[0..@intCast(length)]; -} - pub fn deinitWait(timeout: i64) Error!void { const status = Status.fromInt(nats_c.nats_CloseAndWait(timeout)); return status.raise(); } -// This appears to be a jetstream API, but these two endpoints are trivial, so, whoops. -// I have no clue what this does, since there's basically no -pub const Inbox = opaque { - pub fn create() Error!*Inbox { - var self: *Inbox = undefined; - const status = Status.fromInt(nats_c.natsInbox_Create(@ptrCast(&self))); +// the result of this requires manual deallocation unless it is used to provide the +// signature out-parameter in the natsSignatureHandler callback. Calling it outside of +// that context seems unlikely, but we should probably provide a deinit function so the +// user doesn't have to dig around for libc free to deallocate it. +pub fn sign(encoded_seed: [:0]const u8, input: [:0]const u8) Error![]const u8 { + var result: [*c]u8 = undefined; + var length: c_int = 0; + const status = Status.fromInt(nats_c.nats_Sign( + encoded_seed.ptr, + input.ptr, + &result, + &length, + )); - return status.toError() orelse self; - } + return status.toError() orelse result[0..@intCast(length)]; +} - pub fn destroy(self: *Inbox) void { - nats_c.natsInbox_Destroy(@ptrCast(self)); - } -}; +// Note: an "Inbox" is actually just a string. This API creates a random (unique) +// string suitable for passing as the `reply` field to Message.create or +// Connection.publishRequest. +pub fn createInbox() Error![:0]u8 { + var self: [*c]u8 = undefined; + const status = Status.fromInt(nats_c.natsInbox_Create(@ptrCast(&self))); + + return status.toError() orelse std.mem.sliceTo(self, 0); +} + +pub fn destroyInbox(inbox: [:0]const u8) void { + nats_c.natsInbox_Destroy(@constCast(@ptrCast(inbox.ptr))); +} // I think this is also a jetstream API. This function sure does not seem at all useful // by itself. diff --git a/tests/main.zig b/tests/main.zig index 3cf1919..bdcd393 100644 --- a/tests/main.zig +++ b/tests/main.zig @@ -1,5 +1,4 @@ -const std = @import("std"); - test { + _ = @import("./nats.zig"); _ = @import("./message.zig"); } diff --git a/tests/nats.zig b/tests/nats.zig new file mode 100644 index 0000000..2455116 --- /dev/null +++ b/tests/nats.zig @@ -0,0 +1,96 @@ +const std = @import("std"); + +const nats = @import("nats"); + +test "version" { + const version = nats.getVersion(); + const vernum = nats.getVersionNumber(); + + try std.testing.expectEqualStrings("3.6.1", version); + try std.testing.expectEqual(@as(u32, 0x03_06_01), vernum); + try std.testing.expect(nats.checkCompatibility()); +} + +test "time" { + const now = nats.now(); + const nownano = nats.nowInNanoseconds(); + + nats.sleep(1); + + const later = nats.now(); + const laternano = nats.nowInNanoseconds(); + + try std.testing.expect(later >= now); + try std.testing.expect(laternano >= nownano); +} + +test "init" { + { + try nats.init(nats.default_spin_count); + defer nats.deinit(); + } + + { + // a completely random number + try nats.init(900_142_069); + nats.deinit(); + } + + { + try nats.init(0); + try nats.deinitWait(1000); + } +} + +test "misc" { + { + try nats.init(nats.default_spin_count); + defer nats.deinit(); + + try nats.setMessageDeliveryPoolSize(500); + } + + { + try nats.init(nats.default_spin_count); + defer nats.deinit(); + + // just test that the function is wrapped properly + nats.releaseThreadMemory(); + } + + blk: { + try nats.init(nats.default_spin_count); + defer nats.deinit(); + + // this is a mess of a test that is designed to fail because actually we're + // testing out the error reporting functions instead of signing. Nice bait + // and switch. + const signed = nats.sign("12345678", "12345678") catch { + const err = nats.getLastError(); + std.debug.print("signing failed: {s}\n", .{err.desc}); + + var stackmem = [_]u8{0} ** 512; + var stackbuf: []u8 = &stackmem; + + nats.getLastErrorStack(&stackbuf) catch { + std.debug.print("Actually, the error stack was too big\n", .{}); + break :blk; + }; + + std.debug.print("stack: {s}\n", .{stackbuf}); + break :blk; + }; + + std.heap.raw_c_allocator.free(signed); + } +} + +test "inbox" { + try nats.init(nats.default_spin_count); + defer nats.deinit(); + + const inbox = try nats.createInbox(); + defer nats.destroyInbox(inbox); + + std.debug.print("inbox: {s}\n", .{inbox}); +}