feat: fill in protocol
This commit is contained in:
1 parent
711dc39448
commit
06e9e3fe13
1 file changed
+154
@@ -3141,3 +3141,157 @@ test "TtlAction.fromByte rejects an unknown action" {
|
||||
try std.testing.expectEqual(TtlAction.sweep, try TtlAction.fromByte(3));
|
||||
}
|
||||
|
||||
test "ttl_op expire payload round trips key and seconds" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTtlOp(allocator, .expire, "session:1", 30);
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeTtlOp(payload);
|
||||
try std.testing.expectEqual(TtlAction.expire, args.action);
|
||||
try std.testing.expectEqualStrings("session:1", args.key);
|
||||
try std.testing.expectEqual(@as(u64, 30), args.seconds);
|
||||
}
|
||||
|
||||
test "ttl_op sweep payload carries an empty key and zero seconds" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTtlOp(allocator, .sweep, "", 0);
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeTtlOp(payload);
|
||||
try std.testing.expectEqual(TtlAction.sweep, args.action);
|
||||
try std.testing.expectEqualStrings("", args.key);
|
||||
try std.testing.expectEqual(@as(u64, 0), args.seconds);
|
||||
}
|
||||
|
||||
test "ttl result round trips noKey, noExpiry, and seconds" {
|
||||
const allocator = std.testing.allocator;
|
||||
|
||||
const noKeyPayload = try encodeTtlResult(allocator, .noKey);
|
||||
defer allocator.free(noKeyPayload);
|
||||
try std.testing.expectEqual(ttlmod.TtlResult.noKey, try decodeTtlResult(noKeyPayload));
|
||||
|
||||
const noExpiryPayload = try encodeTtlResult(allocator, .noExpiry);
|
||||
defer allocator.free(noExpiryPayload);
|
||||
try std.testing.expectEqual(ttlmod.TtlResult.noExpiry, try decodeTtlResult(noExpiryPayload));
|
||||
|
||||
const secondsPayload = try encodeTtlResult(allocator, .{ .seconds = 42 });
|
||||
defer allocator.free(secondsPayload);
|
||||
const decoded = try decodeTtlResult(secondsPayload);
|
||||
try std.testing.expectEqual(@as(u64, 42), decoded.seconds);
|
||||
}
|
||||
|
||||
test "decodeTtlResult rejects an unknown kind byte" {
|
||||
const allocator = std.testing.allocator;
|
||||
var buf = std.ArrayList(u8).init(allocator);
|
||||
defer buf.deinit();
|
||||
const w = encode.ByteWriter.init(&buf);
|
||||
try w.byte(200);
|
||||
try std.testing.expectError(error.Malformed, decodeTtlResult(buf.items));
|
||||
}
|
||||
|
||||
test "ttl sweep count round trips" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeTtlSweepCount(allocator, 7);
|
||||
defer allocator.free(payload);
|
||||
try std.testing.expectEqual(@as(u64, 7), try decodeTtlSweepCount(payload));
|
||||
}
|
||||
|
||||
test "coll_ttl_op expire payload round trips action, kind, name and seconds" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeCollTtlOp(allocator, .expire, .hash, "profile", 30);
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeCollTtlOp(payload);
|
||||
try std.testing.expectEqual(TtlAction.expire, args.action);
|
||||
try std.testing.expectEqual(collmod.Kind.hash, args.kind);
|
||||
try std.testing.expectEqualStrings("profile", args.name);
|
||||
try std.testing.expectEqual(@as(u64, 30), args.seconds);
|
||||
}
|
||||
|
||||
test "coll_ttl_op round trips every kind's tag byte" {
|
||||
const allocator = std.testing.allocator;
|
||||
const kinds = [_]collmod.Kind{ .counter, .hash, .set, .list, .zset };
|
||||
for (kinds) |k| {
|
||||
const payload = try encodeCollTtlOp(allocator, .query, k, "n", 0);
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeCollTtlOp(payload);
|
||||
try std.testing.expectEqual(k, args.kind);
|
||||
}
|
||||
}
|
||||
|
||||
test "coll_ttl_op sweep payload carries an empty name and zero seconds" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeCollTtlOp(allocator, .sweep, .counter, "", 0);
|
||||
defer allocator.free(payload);
|
||||
const args = try decodeCollTtlOp(payload);
|
||||
try std.testing.expectEqual(TtlAction.sweep, args.action);
|
||||
try std.testing.expectEqualStrings("", args.name);
|
||||
try std.testing.expectEqual(@as(u64, 0), args.seconds);
|
||||
}
|
||||
|
||||
test "decodeCollTtlOp rejects an unknown kind byte" {
|
||||
const allocator = std.testing.allocator;
|
||||
var buf = std.ArrayList(u8).init(allocator);
|
||||
defer buf.deinit();
|
||||
const w = encode.ByteWriter.init(&buf);
|
||||
try w.byte(@intFromEnum(TtlAction.query));
|
||||
try w.byte('?');
|
||||
try w.putU64(0);
|
||||
try std.testing.expectError(error.Malformed, decodeCollTtlOp(buf.items));
|
||||
}
|
||||
|
||||
test "decodeCollTtlOp rejects an unknown action byte before the kind byte is even read" {
|
||||
const allocator = std.testing.allocator;
|
||||
var buf = std.ArrayList(u8).init(allocator);
|
||||
defer buf.deinit();
|
||||
const w = encode.ByteWriter.init(&buf);
|
||||
try w.byte(200);
|
||||
try w.byte('H');
|
||||
try w.putU64(0);
|
||||
try std.testing.expectError(error.Malformed, decodeCollTtlOp(buf.items));
|
||||
}
|
||||
|
||||
test "CollAction.fromByte rejects an unknown action" {
|
||||
try std.testing.expectError(error.Malformed, CollAction.fromByte(200));
|
||||
try std.testing.expectEqual(CollAction.zset_rank, try CollAction.fromByte(29));
|
||||
}
|
||||
|
||||
test "CollAction.kind groups every action under its collection kind" {
|
||||
try std.testing.expectEqual(collmod.Kind.counter, CollAction.counter_incrby.kind());
|
||||
try std.testing.expectEqual(collmod.Kind.hash, CollAction.hash_getall.kind());
|
||||
try std.testing.expectEqual(collmod.Kind.set, CollAction.set_diff.kind());
|
||||
try std.testing.expectEqual(collmod.Kind.list, CollAction.list_range.kind());
|
||||
try std.testing.expectEqual(collmod.Kind.zset, CollAction.zset_rangebyscore.kind());
|
||||
}
|
||||
|
||||
test "CollAction.isReadOnly separates reads from writes" {
|
||||
try std.testing.expect(CollAction.counter_get.isReadOnly());
|
||||
try std.testing.expect(!CollAction.counter_set.isReadOnly());
|
||||
try std.testing.expect(CollAction.zset_rank.isReadOnly());
|
||||
try std.testing.expect(!CollAction.zset_add.isReadOnly());
|
||||
try std.testing.expect(CollAction.set_inter.isReadOnly());
|
||||
try std.testing.expect(!CollAction.list_lpush.isReadOnly());
|
||||
}
|
||||
|
||||
test "coll_op payload round trips action, name, and a variable arg list" {
|
||||
const allocator = std.testing.allocator;
|
||||
const args = [_][]const u8{ "alice", "10" };
|
||||
const payload = try encodeCollOp(allocator, .zset_add, "leaderboard", &args);
|
||||
defer allocator.free(payload);
|
||||
const decoded = try decodeCollOp(allocator, payload);
|
||||
defer allocator.free(decoded.args);
|
||||
try std.testing.expectEqual(CollAction.zset_add, decoded.action);
|
||||
try std.testing.expectEqualStrings("leaderboard", decoded.name);
|
||||
try std.testing.expectEqual(@as(usize, 2), decoded.args.len);
|
||||
try std.testing.expectEqualStrings("alice", decoded.args[0]);
|
||||
try std.testing.expectEqualStrings("10", decoded.args[1]);
|
||||
}
|
||||
|
||||
test "coll_op payload round trips a zero-arg action" {
|
||||
const allocator = std.testing.allocator;
|
||||
const payload = try encodeCollOp(allocator, .hash_getall, "profile", &.{});
|
||||
defer allocator.free(payload);
|
||||
const decoded = try decodeCollOp(allocator, payload);
|
||||
defer allocator.free(decoded.args);
|
||||
try std.testing.expectEqual(CollAction.hash_getall, decoded.action);
|
||||
try std.testing.expectEqualStrings("profile", decoded.name);
|
||||
try std.testing.expectEqual(@as(usize, 0), decoded.args.len);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user