╭ changed ─────────╮ │src/test/event.zig│ ╰──────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 6 const hash = xit.hash; │ │ 7 │ │ 8 const author = evt.CommitAuthor{ .name = "haxy", .email = "user@haxy" }; │ │ 9 + │ │10 +test "union field storage" { │ │11 + const allocator = std.testing.allocator; │ │12 + var arena = std.heap.ArenaAllocator.init(allocator); │ │13 + defer arena.deinit(); │ │14 + │ │15 + const DB = xit.xitdb.Database(.memory, hash.HashInt(.sha1)); │ │16 + var buffer = std.Io.Writer.Allocating.init(allocator); │ │17 + defer buffer.deinit(); │ │18 + var db = try DB.init(.{ .buffer = &buffer, .max_size = 1_000_000 }); │ │19 + const map = try DB.HashMap(.read_write).init(db.rootCursor()); │ │20 + │ │21 + const Value = union(enum) { │ │22 + empty, │ │23 + finished, │ │24 + data: struct { message: []const u8, note: ?[]const u8 = null }, │ │25 + number: ?u64, │ │26 + }; │ │27 + const Data = struct { value: ?Value }; │ │28 + const key = hash.hashInt(.sha1, "value"); │ │29 + │ │30 + // changing variants must replace the old tag and payload │ │31 + for ([_]?Value{ │ │32 + null, │ │33 + .empty, │ │34 + .{ .data = .{ .message = "first", .note = "note" } }, │ │35 + .{ .data = .{ .message = "second" } }, │ │36 + .{ .number = 42 }, │ │37 + .{ .number = null }, │ │38 + .{ .number = 7 }, │ │39 + .finished, │ │40 + .{ .data = .{ .message = "third" } }, │ │41 + null, │ │42 + }) |value| { │ │43 + try evt.upsert(Data, DB, .sha1, map, .{ .value = value }); │ │44 + const stored = try evt.read(Data, DB, .sha1, &arena, map.readOnly()); │ │45 + try std.testing.expectEqualDeep(value, stored.value); │ │46 + if (value) |active| { │ │47 + const cursor = (try map.getCursor(key)) orelse return error.NotFound; │ │48 + switch (active) { │ │49 + .empty, .finished => try std.testing.expectEqualStrings(@tagName(active), try cursor.readBytesAlloc(arena.allocator(), null)),│ │50 + else => try std.testing.expectEqual(.hash_map, cursor.slot().tag), │ │51 + } │ │52 + } else { │ │53 + try std.testing.expectEqual(null, try map.getCursor(key)); │ │54 + } │ │55 + } │ │56 + │ │57 + // a payload-bearing variant cannot be stored as just its name │ │58 + try map.put(key, .{ .bytes = "data" }); │ │59 + try std.testing.expectError(error.InvalidUnion, evt.read(Data, DB, .sha1, &arena, map.readOnly())); │ │60 +} │ │61 │ │62 test "rebase" { │ │63 const io = std.testing.io; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯