From 875b1b63442de3c9fd05e7d6c5168a048e143eaa Mon Sep 17 00:00:00 2001 From: torque Date: Fri, 1 Dec 2023 22:35:18 -0800 Subject: [PATCH] start adding tests --- build.zig | 15 +++++ tests/main.zig | 5 ++ tests/reify.zig | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 tests/main.zig create mode 100644 tests/reify.zig diff --git a/build.zig b/build.zig index 78beac1..8fb785d 100644 --- a/build.zig +++ b/build.zig @@ -2,11 +2,26 @@ const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); const nice = b.addModule("nice", .{ .source_file = .{ .path = "src/nice.zig" }, }); + const tests = b.addTest(.{ + .name = "nice-unit-tests", + .root_source_file = .{ .path = "tests/main.zig" }, + .target = target, + .optimize = optimize, + }); + + tests.addModule("nice", nice); + + const run_main_tests = b.addRunArtifact(tests); + const test_step = b.step("test", "Run tests"); + test_step.dependOn(&b.addInstallArtifact(tests, .{}).step); + test_step.dependOn(&run_main_tests.step); + add_examples(b, .{ .target = target, .nice_mod = nice, diff --git a/tests/main.zig b/tests/main.zig new file mode 100644 index 0000000..ed33f08 --- /dev/null +++ b/tests/main.zig @@ -0,0 +1,5 @@ +comptime { + if (@import("builtin").is_test) { + _ = @import("./reify.zig"); + } +} diff --git a/tests/reify.zig b/tests/reify.zig new file mode 100644 index 0000000..56d504e --- /dev/null +++ b/tests/reify.zig @@ -0,0 +1,144 @@ +const std = @import("std"); + +const nice = @import("nice"); + +fn reifyScalar(comptime scalar: []const u8, expected: anytype) !void { + try reifyScalarWithOptions(scalar, expected, .{}); +} + +fn reifyScalarWithOptions(comptime scalar: []const u8, expected: anytype, options: nice.parser.Options) !void { + const allocator = std.testing.allocator; + var diagnostics = nice.Diagnostics{}; + const parsed = try nice.parseBufferTo( + @TypeOf(expected), + allocator, + scalar ++ "\n", + &diagnostics, + options, + ); + defer parsed.deinit(); + + try std.testing.expectEqual(expected, parsed.value); +} + +test "reify integer" { + try reifyScalar("123", @as(u8, 123)); + try reifyScalar("0123", @as(u8, 123)); + try reifyScalar("1_23", @as(u8, 123)); + try reifyScalar("-01_23", @as(i8, -123)); +} + +test "reify hexadecimal" { + try reifyScalar("0x123", @as(i64, 0x123)); + try reifyScalar("0x0123", @as(i64, 0x123)); + try reifyScalar("0x01_23", @as(i64, 0x123)); + try reifyScalar("-0x01_23", @as(i64, -0x123)); +} + +test "reify octal" { + try reifyScalar("0o123", @as(i64, 0o123)); + try reifyScalar("0o0123", @as(i64, 0o123)); + try reifyScalar("0o01_23", @as(i64, 0o123)); + try reifyScalar("-0o01_23", @as(i64, -0o123)); +} + +test "reify binary" { + try reifyScalar("0b1011", @as(i5, 0b1011)); + try reifyScalar("0b01011", @as(i5, 0b1011)); + try reifyScalar("0b010_11", @as(i5, 0b1011)); + try reifyScalar("-0b010_11", @as(i5, -0b1011)); +} + +test "reify float" { + try reifyScalar("0.25", @as(f32, 0.25)); + try reifyScalar("0.2_5", @as(f32, 0.25)); + try reifyScalar("00.250", @as(f32, 0.25)); + try reifyScalar("-0.25", @as(f32, -0.25)); +} + +test "reify hexfloat" { + try reifyScalar("0x0.25", @as(f64, 0x0.25)); + try reifyScalar("0x0.2_5", @as(f64, 0x0.25)); + try reifyScalar("0x0.250p1", @as(f64, 0x0.25p1)); + try reifyScalar("-0x0.25", @as(f64, -0x0.25)); +} + +test "reify true" { + try reifyScalar("true", true); + try reifyScalar("True", true); + try reifyScalar("yes", true); + try reifyScalar("on", true); +} + +test "reify false" { + try reifyScalar("false", false); + try reifyScalar("False", false); + try reifyScalar("no", false); + try reifyScalar("off", false); +} + +test "reify custom true" { + const options = nice.parser.Options{ .truthy_boolean_scalars = &.{"correct"} }; + try reifyScalarWithOptions("correct", true, options); +} + +test "reify true case insensitive" { + try std.testing.expectError(error.BadValue, reifyScalar("TRUE", true)); + const options = nice.parser.Options{ .case_insensitive_scalar_coersion = true }; + try reifyScalarWithOptions("TRUE", true, options); +} + +test "reify custom false" { + const options = nice.parser.Options{ .falsy_boolean_scalars = &.{"incorrect"} }; + try reifyScalarWithOptions("incorrect", false, options); +} + +test "reify false case insensitive" { + try std.testing.expectError(error.BadValue, reifyScalar("FALSE", false)); + const options = nice.parser.Options{ .case_insensitive_scalar_coersion = true }; + try reifyScalarWithOptions("FALSE", false, options); +} + +test "reify null" { + try reifyScalar("null", @as(?u8, null)); + try reifyScalar("nil", @as(?u8, null)); + try reifyScalar("None", @as(?u8, null)); +} + +test "reify custom null" { + const options = nice.parser.Options{ .null_scalars = &.{"nothing"} }; + try reifyScalarWithOptions("nothing", @as(?u8, null), options); +} + +test "reify null case insensitive" { + // this is a little weird because when the null string mismatches, it will try to + // parse the child optional type and produce either a value or an error from that, + // so the error received depends on whether or not the optional child type fails to + // parse the given value. + try std.testing.expectError(error.InvalidCharacter, reifyScalar("NULL", @as(?u8, null))); + const options = nice.parser.Options{ .case_insensitive_scalar_coersion = true }; + try reifyScalarWithOptions("NULL", @as(?u8, null), options); +} + +test "reify void" { + // A void scalar cannot exist on its own as it is not distinguishable from an empty + // document. + const Void = struct { void: void }; + try reifyScalar("void:", Void{ .void = void{} }); +} + +test "reify void scalar" { + const options = nice.parser.Options{ .default_object = .scalar }; + try reifyScalarWithOptions("", void{}, options); +} + +test "reify enum" { + const Enum = enum { one, two }; + try reifyScalar(".one", Enum.one); +} + +test "reify enum no dot" { + const options = nice.parser.Options{ .expect_enum_dot = false }; + const Enum = enum { one, two }; + try reifyScalarWithOptions("two", Enum.two, options); +}