feat: expand protocol
This commit is contained in:
1 parent
b94896cb62
commit
96ab73e9e3
1 file changed
+161
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user