feat: expand protocol

This commit is contained in:
dualfroz committed 2026-09-08 16:10:29 +02:00
1 parent b94896cb62
commit 96ab73e9e3
1 file changed
+161
+161
View File
@@ -3452,3 +3452,164 @@ test "empty txn_op entry list round trips" {
try std.testing.expectEqual(@as(usize, 0), decoded.len); try std.testing.expectEqual(@as(usize, 0), decoded.len);
} }
test "decodeTxnOp rejects an unknown verb byte" {
const allocator = std.testing.allocator;
var buf = std.ArrayList(u8).init(allocator);
defer buf.deinit();
const w = encode.ByteWriter.init(&buf);
try w.putU32(1);
try w.byte(9);
try std.testing.expectError(error.Malformed, decodeTxnOp(allocator, buf.items));
}
test "txn_op result round trips the applied count" {
const allocator = std.testing.allocator;
const payload = try encodeTxnResult(allocator, 7);
defer allocator.free(payload);
try std.testing.expectEqual(@as(u32, 7), try decodeTxnResult(payload));
}
test "table_window args round trip a ranking spec with a partition, an order-by, and an expr" {
const allocator = std.testing.allocator;
const orderBy = [_]querymod.OrderBy{.{ .field = "day", .descending = false }};
const partitionBy = [_][]const u8{"city"};
const specs = [_]windowmod.WindowSpec{.{ .field = "", .kind = .row_number }};
const payload = try encodeTableWindow(allocator, "orders", &specs, &partitionBy, &orderBy, 0, 0, "total gt i:10", .rows);
defer allocator.free(payload);
const args = try decodeTableWindow(allocator, payload);
defer allocator.free(args.specs);
defer allocator.free(args.partitionBy);
defer allocator.free(args.orderBy);
try std.testing.expectEqualStrings("orders", args.table);
try std.testing.expectEqual(@as(usize, 1), args.specs.len);
try std.testing.expectEqual(windowmod.WindowKind.row_number, args.specs[0].kind);
try std.testing.expectEqualStrings("", args.specs[0].field);
try std.testing.expectEqual(@as(usize, 1), args.partitionBy.len);
try std.testing.expectEqualStrings("city", args.partitionBy[0]);
try std.testing.expectEqual(@as(usize, 1), args.orderBy.len);
try std.testing.expectEqualStrings("day", args.orderBy[0].field);
try std.testing.expect(!args.orderBy[0].descending);
try std.testing.expectEqualStrings("total gt i:10", args.exprText);
}
test "table_window args round trip a sum spec with no partition, no order-by, and an empty expr" {
const allocator = std.testing.allocator;
const specs = [_]windowmod.WindowSpec{.{ .field = "total", .kind = .sum }};
const payload = try encodeTableWindow(allocator, "orders", &specs, &.{}, &.{}, 0, 0, "", .rows);
defer allocator.free(payload);
const args = try decodeTableWindow(allocator, payload);
defer allocator.free(args.specs);
defer allocator.free(args.partitionBy);
defer allocator.free(args.orderBy);
try std.testing.expectEqual(@as(usize, 1), args.specs.len);
try std.testing.expectEqual(windowmod.WindowKind.sum, args.specs[0].kind);
try std.testing.expectEqualStrings("total", args.specs[0].field);
try std.testing.expectEqual(@as(usize, 0), args.partitionBy.len);
try std.testing.expectEqual(@as(usize, 0), args.orderBy.len);
try std.testing.expectEqualStrings("", args.exprText);
}
test "table_window args round trip a count_distinct spec alongside sum, no extra wire bytes needed" {
const allocator = std.testing.allocator;
const orderBy = [_]querymod.OrderBy{.{ .field = "day" }};
const specs = [_]windowmod.WindowSpec{
.{ .field = "tag", .kind = .count_distinct },
.{ .field = "amount", .kind = .sum },
};
const payload = try encodeTableWindow(allocator, "orders", &specs, &.{}, &orderBy, 0, 0, "", .rows);
defer allocator.free(payload);
const args = try decodeTableWindow(allocator, payload);
defer allocator.free(args.specs);
defer allocator.free(args.partitionBy);
defer allocator.free(args.orderBy);
try std.testing.expectEqual(@as(usize, 2), args.specs.len);
try std.testing.expectEqual(windowmod.WindowKind.count_distinct, args.specs[0].kind);
try std.testing.expectEqualStrings("tag", args.specs[0].field);
try std.testing.expectEqual(windowmod.WindowKind.sum, args.specs[1].kind);
}
test "table_window args round trip first_value/last_value specs alongside a partition/order/RANGE frame" {
const allocator = std.testing.allocator;
const orderBy = [_]querymod.OrderBy{.{ .field = "day" }};
const partitionBy = [_][]const u8{"city"};
const specs = [_]windowmod.WindowSpec{
.{ .field = "amount", .kind = .first_value },
.{ .field = "amount", .kind = .last_value },
};
const payload = try encodeTableWindow(allocator, "orders", &specs, &partitionBy, &orderBy, 0, 0, "", .range);
defer allocator.free(payload);
const args = try decodeTableWindow(allocator, payload);
defer allocator.free(args.specs);
defer allocator.free(args.partitionBy);
defer allocator.free(args.orderBy);
try std.testing.expectEqual(@as(usize, 2), args.specs.len);
try std.testing.expectEqual(windowmod.WindowKind.first_value, args.specs[0].kind);
try std.testing.expectEqualStrings("amount", args.specs[0].field);
try std.testing.expectEqual(windowmod.WindowKind.last_value, args.specs[1].kind);
try std.testing.expectEqualStrings("amount", args.specs[1].field);
try std.testing.expectEqual(windowmod.FrameMode.range, args.frame);
}
test "table_window args round trip MULTIPLE specs sharing one partition/order/frame" {
const allocator = std.testing.allocator;
const specs = [_]windowmod.WindowSpec{
.{ .field = "total", .kind = .sum },
.{ .field = "total", .kind = .avg },
.{ .field = "", .kind = .rank },
};
const payload = try encodeTableWindow(allocator, "orders", &specs, &.{}, &.{}, 0, 0, "", .rows);
defer allocator.free(payload);
const args = try decodeTableWindow(allocator, payload);
defer allocator.free(args.specs);
defer allocator.free(args.partitionBy);
defer allocator.free(args.orderBy);
try std.testing.expectEqual(@as(usize, 3), args.specs.len);
try std.testing.expectEqual(windowmod.WindowKind.sum, args.specs[0].kind);
try std.testing.expectEqualStrings("total", args.specs[0].field);
try std.testing.expectEqual(windowmod.WindowKind.avg, args.specs[1].kind);
try std.testing.expectEqualStrings("total", args.specs[1].field);
try std.testing.expectEqual(windowmod.WindowKind.rank, args.specs[2].kind);
try std.testing.expectEqualStrings("", args.specs[2].field);
}
test "table_window args round trip a nonzero offset and limit" {
const allocator = std.testing.allocator;
const specs = [_]windowmod.WindowSpec{.{ .field = "", .kind = .rank }};
const payload = try encodeTableWindow(allocator, "orders", &specs, &.{}, &.{}, 2, 5, "", .rows);
defer allocator.free(payload);
const args = try decodeTableWindow(allocator, payload);
defer allocator.free(args.specs);
defer allocator.free(args.partitionBy);
defer allocator.free(args.orderBy);
try std.testing.expectEqual(@as(u32, 2), args.offset);
try std.testing.expectEqual(@as(u32, 5), args.limit);
}
test "table_window args round trip a RANGE frame, and default to ROWS when the byte is 0" {
const allocator = std.testing.allocator;
const order = [_]querymod.OrderBy{.{ .field = "day", .descending = false }};
const specs = [_]windowmod.WindowSpec{.{ .field = "amount", .kind = .sum }};
const rangePayload = try encodeTableWindow(allocator, "orders", &specs, &.{}, &order, 0, 0, "", .range);
defer allocator.free(rangePayload);
const rangeArgs = try decodeTableWindow(allocator, rangePayload);
defer allocator.free(rangeArgs.specs);
defer allocator.free(rangeArgs.partitionBy);
defer allocator.free(rangeArgs.orderBy);
try std.testing.expectEqual(windowmod.FrameMode.range, rangeArgs.frame);
const rowsPayload = try encodeTableWindow(allocator, "orders", &specs, &.{}, &order, 0, 0, "", .rows);
defer allocator.free(rowsPayload);
const rowsArgs = try decodeTableWindow(allocator, rowsPayload);
defer allocator.free(rowsArgs.specs);
defer allocator.free(rowsArgs.partitionBy);
defer allocator.free(rowsArgs.orderBy);
try std.testing.expectEqual(windowmod.FrameMode.rows, rowsArgs.frame);
}