diff options
Diffstat (limited to 'src/test/values.zig')
| -rw-r--r-- | src/test/values.zig | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/src/test/values.zig b/src/test/values.zig new file mode 100644 index 0000000..7339f22 --- /dev/null +++ b/src/test/values.zig @@ -0,0 +1,247 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const testing = std.testing; + +pub const gc = @import("../zisp/gc.zig"); +pub const io = @import("../zisp/io.zig"); +pub const lib = @import("../zisp/lib.zig"); +pub const value = @import("../zisp/value.zig"); + +pub const Hval = gc.Hval; + +pub const ShortString = value.ShortString; +pub const Value = value.Value; + +test "double" { + const d1: f64 = 0.123456789; + const d2: f64 = -0.987654321; + const v1 = value.double.pack(d1); + const v2 = value.double.pack(d2); + const v3 = value.double.add(v1, v2); + const result = value.double.unpack(v3); + + try testing.expect(value.double.check(v1)); + try testing.expect(value.double.check(v2)); + try testing.expect(value.double.check(v3)); + + try testing.expectEqual(d1 + d2, result); +} + +test "fixnum" { + const int1: i64 = 123456789; + const int2: i64 = -987654321; + const v1 = value.fixnum.pack(int1); + const v2 = value.fixnum.pack(int2); + const v3 = value.fixnum.add(v1, v2); + const result = value.fixnum.unpack(v3); + + try testing.expect(value.fixnum.check(v1)); + try testing.expect(value.fixnum.check(v2)); + try testing.expect(value.fixnum.check(v3)); + + try testing.expectEqual(int1 + int2, result); +} + +test "ptr" { + const ptr = value.ptr; + + const val: *Hval = @ptrFromInt(256); + const tag = ptr.Tag.pair; + + const p = ptr.pack(val, tag); + try testing.expect(ptr.check(p)); + try testing.expect(ptr.checkZispTag(p, tag)); + try testing.expect(ptr.checkStrong(p)); + + const pv, const pt = ptr.unpack(p); + try testing.expectEqual(val, pv); + try testing.expectEqual(tag, pt); + + var w = ptr.makeWeak(p); + try testing.expect(ptr.check(w)); + try testing.expect(ptr.checkZispTag(w, tag)); + try testing.expect(ptr.checkWeak(w)); + try testing.expectEqual(true, value.boole.unpack(ptr.predWeak(w))); + try testing.expectEqual(false, value.boole.unpack(ptr.predWeakNull(w))); + + const wv, const wt = ptr.unpack(w); + try testing.expectEqual(val, wv); + try testing.expectEqual(tag, wt); + + const wv2, const wt2 = ptr.unpack(ptr.getWeak(w)); + try testing.expectEqual(val, wv2); + try testing.expectEqual(tag, wt2); + + ptr.setWeakNull(&w); + try testing.expect(ptr.check(w)); + try testing.expect(ptr.checkWeak(w)); + try testing.expect(ptr.isWeakNull(w)); + try testing.expectEqual(true, value.boole.unpack(ptr.predWeak(w))); + try testing.expectEqual(true, value.boole.unpack(ptr.predWeakNull(w))); + try testing.expectEqual(false, value.boole.unpack(ptr.getWeak(w))); +} + +test "fptr" { + const ptr = value.ptr; + + const int1: u50 = 0; + const int2: u50 = std.math.maxInt(u50); + + const f1 = ptr.packForeign(int1); + try testing.expect(ptr.checkForeign(f1)); + try testing.expectEqual(int1, ptr.unpackForeign(f1)); + + const f2 = ptr.packForeign(int2); + try testing.expect(ptr.checkForeign(f2)); + try testing.expectEqual(int2, ptr.unpackForeign(f2)); +} + +test "rune" { + const r = value.rune.pack("test"); + try testing.expect(value.rune.check(r)); + + const s = value.rune.unpack(r); + try testing.expectEqualStrings("test", s.slice()); +} + +const SstrImpl = struct { SstrPack, SstrUnpack }; +const SstrPack = *const fn ([]const u8) Value; +const SstrUnpack = *const fn (Value) ShortString; + +test "sstr" { + const impls = [_]SstrImpl{ + .{ value.sstr.pack, value.sstr.unpack }, + // .{ value.sstr.pack1, value.sstr.unpack1 }, + // .{ value.sstr.pack2, value.sstr.unpack2 }, + // .{ value.sstr.pack3, value.sstr.unpack3 }, + // .{ value.sstr.pack4, value.sstr.unpack4 }, + }; + + for (impls) |impl| { + try testSstr(impl); + } + + if (impls.len > 1) { + const iters = switch (@import("builtin").mode) { + .Debug, .ReleaseSmall => 10_000_000, + .ReleaseSafe => 100_000_000, + .ReleaseFast => 1_000_000_000, + }; + std.debug.print("Benchmarking sstr with {} iters.\n", .{iters}); + inline for (impls, 0..) |impl, i| { + try benchmarkSstr(impl, i, iters); + } + } +} + +fn testSstr(impl: SstrImpl) !void { + const pack, const unpack = impl; + + const ss1 = pack("1"); + const ss2 = pack("123"); + const ss3 = pack("123456"); + + const s1 = unpack(ss1); + const s2 = unpack(ss2); + const s3 = unpack(ss3); + + try testing.expect(value.sstr.check(ss1)); + try testing.expect(value.sstr.check(ss2)); + try testing.expect(value.sstr.check(ss3)); + + try testing.expectEqualStrings("1", s1.slice()); + try testing.expectEqualStrings("123", s2.slice()); + try testing.expectEqualStrings("123456", s3.slice()); +} + +fn benchmarkSstr(impl: SstrImpl, id: usize, iters: usize) !void { + const pack, const unpack = impl; + + var timer = try std.time.Timer.start(); + var ns: f64 = undefined; + var secs: f64 = undefined; + + var ss1: Value = undefined; + var ss2: Value = undefined; + var ss3: Value = undefined; + + for (0..iters) |_i| { + _ = _i; + ss1 = pack("1"); + ss2 = pack("123"); + ss3 = pack("123456"); + } + + ns = @floatFromInt(timer.lap()); + secs = ns / 1_000_000_000; + + std.debug.print("pack{}: {d:.3}s\t", .{ id, secs }); + + for (0..iters) |_i| { + _ = _i; + std.mem.doNotOptimizeAway(unpack(ss1)); + std.mem.doNotOptimizeAway(unpack(ss2)); + std.mem.doNotOptimizeAway(unpack(ss3)); + } + + ns = @floatFromInt(timer.lap()); + secs = ns / 1_000_000_000; + + std.debug.print("unpack{}: {d:.3}s\n", .{ id, secs }); +} + +test "char" { + const c1 = value.char.pack('\x00'); + try testing.expect(value.char.check(c1)); + try testing.expectEqual('\x00', value.char.unpack(c1)); + + const c2 = value.char.pack('😀'); + try testing.expect(value.char.check(c2)); + try testing.expectEqual('😀', value.char.unpack(c2)); +} + +test "misc" { + const f = value.boole.pack(false); + try testing.expect(value.f.eq(f)); + try testing.expect(value.boole.check(f)); + try testing.expectEqual(false, value.boole.unpack(f)); + try testing.expect(value.boole.unpack(value.boole.pred(f))); + + const t = value.boole.pack(true); + try testing.expect(value.t.eq(t)); + try testing.expect(value.boole.check(t)); + try testing.expectEqual(true, value.boole.unpack(t)); + try testing.expect(value.boole.unpack(value.boole.pred(t))); + + const nil = value.nil; + try testing.expect(value.boole.unpack(value.misc.isNil(nil))); + + const eof = value.eof; + try testing.expect(value.boole.unpack(value.misc.isEof(eof))); +} + +test "pair" { + const v1 = value.fixnum.pack(1); + const v2 = value.fixnum.pack(2); + + const v3 = value.fixnum.pack(3); + const v4 = value.fixnum.pack(4); + + const p = value.pair.cons(v1, v2); + try testing.expect(value.pair.check(p)); + try testing.expect(value.boole.unpack(value.pair.pred(p))); + + const car = value.pair.car(p); + const cdr = value.pair.cdr(p); + try testing.expectEqual(1, value.fixnum.unpack(car)); + try testing.expectEqual(2, value.fixnum.unpack(cdr)); + + value.pair.setcar(p, v3); + value.pair.setcdr(p, v4); + + const car2 = value.pair.car(p); + const cdr2 = value.pair.cdr(p); + try testing.expectEqual(3, value.fixnum.unpack(car2)); + try testing.expectEqual(4, value.fixnum.unpack(cdr2)); +} |
