feat: expand protocol
This commit is contained in:
1 parent
4f10674feb
commit
6f0790ed87
1 file changed
+159
@@ -2355,3 +2355,162 @@ test "entries round trip and are independently owned" {
|
||||
const payload = try encodeEntries(allocator, &entries);
|
||||
defer allocator.free(payload);
|
||||
|
||||
const owned = try decodeEntries(allocator, payload);
|
||||
defer freeOwnedEntries(allocator, owned);
|
||||
|
||||
try std.testing.expectEqual(@as(usize, 2), owned.len);
|
||||
try std.testing.expectEqualStrings("a", owned[0].key);
|
||||
try std.testing.expectEqualStrings("1", owned[0].value);
|
||||
try std.testing.expectEqualStrings("b", owned[1].key);
|
||||
try std.testing.expectEqualStrings("2", owned[1].value);
|
||||
}
|
||||
|
||||
test "empty entry list round trips" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeEntries(allocator, &[_]dbmod.Entry{});
|
||||
defer allocator.free(payload);
|
||||
const owned = try decodeEntries(allocator, payload);
|
||||
defer freeOwnedEntries(allocator, owned);
|
||||
try std.testing.expectEqual(@as(usize, 0), owned.len);
|
||||
}
|
||||
|
||||
test "batch ops round trip put and delete" {
|
||||
const allocator = std.testing.allocator;
|
||||
const ops = [_]BatchOp{
|
||||
.{ .put = .{ .key = "a", .value = "1" } },
|
||||
.{ .del = "b" },
|
||||
};
|
||||
const payload = try encodeBatch(allocator, &ops);
|
||||
defer allocator.free(payload);
|
||||
|
||||
const decoded = try decodeBatch(allocator, payload);
|
||||
defer allocator.free(decoded);
|
||||
|
||||
try std.testing.expectEqual(@as(usize, 2), decoded.len);
|
||||
try std.testing.expectEqualStrings("a", decoded[0].put.key);
|
||||
try std.testing.expectEqualStrings("1", decoded[0].put.value);
|
||||
try std.testing.expectEqualStrings("b", decoded[1].del);
|
||||
}
|
||||
|
||||
test "decodeBatch rejects an unknown op kind" {
|
||||
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, decodeBatch(allocator, buf.items));
|
||||
}
|
||||
|
||||
test "stats round trip preserves all fields including per-level detail" {
|
||||
const allocator = std.testing.allocator;
|
||||
var stats = dbmod.Stats{};
|
||||
stats.memtableEntries = 3;
|
||||
stats.memtableBytes = 128;
|
||||
stats.sstableCount = 2;
|
||||
stats.liveEntries = 100;
|
||||
stats.physicalBytes = 4096;
|
||||
stats.cacheHits = 10;
|
||||
stats.cacheMisses = 4;
|
||||
stats.nextSeq = 55;
|
||||
stats.levels[0] = .{ .tables = 1, .entries = 50, .physicalBytes = 2048 };
|
||||
stats.levels[3] = .{ .tables = 2, .entries = 50, .physicalBytes = 2048 };
|
||||
|
||||
const payload = try encodeStats(allocator, stats);
|
||||
defer allocator.free(payload);
|
||||
const decoded = try decodeStats(payload);
|
||||
|
||||
try std.testing.expectEqual(stats.memtableEntries, decoded.memtableEntries);
|
||||
try std.testing.expectEqual(stats.nextSeq, decoded.nextSeq);
|
||||
try std.testing.expectEqual(stats.levels[0].tables, decoded.levels[0].tables);
|
||||
try std.testing.expectEqual(stats.levels[3].entries, decoded.levels[3].entries);
|
||||
try std.testing.expectEqual(@as(f64, decoded.cacheHitRate()), decoded.cacheHitRate());
|
||||
}
|
||||
|
||||
test "table select args round trip with a non-empty expr" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTableSelect(allocator, "users", "city eq s:warsaw", 0, 0, &.{});
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeTableSelect(allocator, payload);
|
||||
defer allocator.free(args.orderBy);
|
||||
try std.testing.expectEqualStrings("users", args.table);
|
||||
try std.testing.expectEqualStrings("city eq s:warsaw", args.exprText);
|
||||
try std.testing.expectEqual(@as(u32, 0), args.offset);
|
||||
try std.testing.expectEqual(@as(u32, 0), args.limit);
|
||||
try std.testing.expectEqual(@as(usize, 0), args.orderBy.len);
|
||||
}
|
||||
|
||||
test "table select args round trip with an empty expr means select all" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTableSelect(allocator, "users", "", 0, 0, &.{});
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeTableSelect(allocator, payload);
|
||||
defer allocator.free(args.orderBy);
|
||||
try std.testing.expectEqualStrings("users", args.table);
|
||||
try std.testing.expectEqualStrings("", args.exprText);
|
||||
}
|
||||
|
||||
test "table select args round trip with a page window" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTableSelect(allocator, "users", "age gt i:10", 5, 3, &.{});
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeTableSelect(allocator, payload);
|
||||
defer allocator.free(args.orderBy);
|
||||
try std.testing.expectEqualStrings("users", args.table);
|
||||
try std.testing.expectEqualStrings("age gt i:10", args.exprText);
|
||||
try std.testing.expectEqual(@as(u32, 5), args.offset);
|
||||
try std.testing.expectEqual(@as(u32, 3), args.limit);
|
||||
}
|
||||
|
||||
test "table select args round trip with an ascending order-by" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTableSelect(allocator, "users", "", 0, 0, &.{.{ .field = "age" }});
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeTableSelect(allocator, payload);
|
||||
defer allocator.free(args.orderBy);
|
||||
try std.testing.expectEqual(@as(usize, 1), args.orderBy.len);
|
||||
try std.testing.expectEqualStrings("age", args.orderBy[0].field);
|
||||
try std.testing.expectEqual(false, args.orderBy[0].descending);
|
||||
}
|
||||
|
||||
test "table select args round trip with a descending order-by, page, and expr all together" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTableSelect(allocator, "users", "city eq s:warsaw", 2, 5, &.{.{ .field = "score", .descending = true }});
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeTableSelect(allocator, payload);
|
||||
defer allocator.free(args.orderBy);
|
||||
try std.testing.expectEqualStrings("users", args.table);
|
||||
try std.testing.expectEqualStrings("city eq s:warsaw", args.exprText);
|
||||
try std.testing.expectEqual(@as(u32, 2), args.offset);
|
||||
try std.testing.expectEqual(@as(u32, 5), args.limit);
|
||||
try std.testing.expectEqualStrings("score", args.orderBy[0].field);
|
||||
try std.testing.expectEqual(true, args.orderBy[0].descending);
|
||||
}
|
||||
|
||||
test "table select args round trip with two order-by columns in given order" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTableSelect(allocator, "users", "", 0, 0, &.{ .{ .field = "city" }, .{ .field = "score", .descending = true } });
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeTableSelect(allocator, payload);
|
||||
defer allocator.free(args.orderBy);
|
||||
try std.testing.expectEqual(@as(usize, 2), args.orderBy.len);
|
||||
try std.testing.expectEqualStrings("city", args.orderBy[0].field);
|
||||
try std.testing.expectEqual(false, args.orderBy[0].descending);
|
||||
try std.testing.expectEqualStrings("score", args.orderBy[1].field);
|
||||
try std.testing.expectEqual(true, args.orderBy[1].descending);
|
||||
}
|
||||
|
||||
test "decodeTableSelect rejects an order-by count claiming more columns than were actually encoded" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTableSelect(allocator, "users", "", 0, 0, &.{.{ .field = "age" }});
|
||||
defer allocator.free(payload);
|
||||
// The count byte sits right after the two u32 page fields: 4 (table
|
||||
// len prefix) + 5 ("users") + 4 (offset) + 4 (limit).
|
||||
const countBytePos = 4 + 5 + 4 + 4;
|
||||
try std.testing.expectEqual(@as(u8, 1), payload[countBytePos]);
|
||||
var corrupted = try allocator.dupe(u8, payload);
|
||||
defer allocator.free(corrupted);
|
||||
corrupted[countBytePos] = 200;
|
||||
try std.testing.expectError(error.Malformed, decodeTableSelect(allocator, corrupted));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user