feat: grow server

This commit is contained in:
dualfroz committed 2026-09-11 22:47:43 +02:00
1 parent 555977be6b
commit ea08f11a80
1 file changed
+159
+159
View File
@@ -4535,3 +4535,162 @@ test "server table_window rejects a RANGE frame combined with lag as bad_request
defer db.close(); defer db.close();
try seedAggregateOrders(allocator, &db); try seedAggregateOrders(allocator, &db);
const address = try std.net.Address.parseIp("127.0.0.1", 0);
var server = try Server.init(allocator, &db, address);
try server.start();
defer server.stop();
const client_mod = @import("client.zig");
var client = try client_mod.Client.connect(allocator, server.boundAddress());
defer client.close();
const orderBy = [_]querymod.OrderBy{.{ .field = "total", .descending = false }};
const specs = [_]windowmod.WindowSpec{.{ .field = "total", .kind = .lead }};
const err = client.tableWindow(allocator, "orders", &specs, &.{}, &orderBy, 0, 0, "", .range);
try std.testing.expectError(client_mod.ClientError.ServerBadRequest, err);
}
test "server table_window first_value/last_value read the current RANGE tie group's edges, over real TCP" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
const path = try tmp.dir.realpathAlloc(allocator, ".");
defer allocator.free(path);
var db = try testDb(allocator, path);
defer db.close();
try seedAggregateOrders(allocator, &db);
const address = try std.net.Address.parseIp("127.0.0.1", 0);
var server = try Server.init(allocator, &db, address);
try server.start();
defer server.stop();
const client_mod = @import("client.zig");
var client = try client_mod.Client.connect(allocator, server.boundAddress());
defer client.close();
const orderBy = [_]querymod.OrderBy{.{ .field = "total", .descending = false }};
const specs = [_]windowmod.WindowSpec{
.{ .field = "total", .kind = .first_value },
.{ .field = "total", .kind = .last_value },
};
const results = try client.tableWindow(allocator, "orders", &specs, &.{}, &orderBy, 0, 0, "", .range);
defer protocol.freeWindowRows(allocator, results);
// Sorted by total ascending: krakow/40, warsaw/100, warsaw/250 - no ties,
// so RANGE reduces to one tie group per row (same as ROWS): first_value
// is always the partition's first row (40, frame start is unaffected by
// ties), but last_value is each row's OWN value since it is its own
// singleton tie group.
try std.testing.expectEqual(@as(usize, 3), results.len);
for (results) |r| try std.testing.expectEqual(@as(i64, 40), r.values[0].int);
try std.testing.expectEqual(@as(i64, 40), results[0].values[1].int);
try std.testing.expectEqual(@as(i64, 100), results[1].values[1].int);
try std.testing.expectEqual(@as(i64, 250), results[2].values[1].int);
}
test "server table_window nth_value reads a fixed frame position, default at the sequence edge, over real TCP" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
const path = try tmp.dir.realpathAlloc(allocator, ".");
defer allocator.free(path);
var db = try testDb(allocator, path);
defer db.close();
try seedAggregateOrders(allocator, &db);
const address = try std.net.Address.parseIp("127.0.0.1", 0);
var server = try Server.init(allocator, &db, address);
try server.start();
defer server.stop();
const client_mod = @import("client.zig");
var client = try client_mod.Client.connect(allocator, server.boundAddress());
defer client.close();
const orderBy = [_]querymod.OrderBy{.{ .field = "total", .descending = false }};
const specs = [_]windowmod.WindowSpec{.{ .field = "total", .kind = .nth_value, .offset = 2, .default = .{ .int = -1 } }};
const results = try client.tableWindow(allocator, "orders", &specs, &.{}, &orderBy, 0, 0, "", .rows);
defer protocol.freeWindowRows(allocator, results);
// Sorted: krakow/40, warsaw/100, warsaw/250. Position 2 (n=2) needs a
// frame of at least size 2 - the first row's ROWS frame is still just
// itself (size 1), so it falls back to the caller's default (-1); the
// remaining two rows both see position 2's value, 100.
try std.testing.expectEqual(@as(usize, 3), results.len);
try std.testing.expectEqual(@as(i64, -1), results[0].values[0].int);
try std.testing.expectEqual(@as(i64, 100), results[1].values[0].int);
try std.testing.expectEqual(@as(i64, 100), results[2].values[0].int);
}
test "server table_window count_distinct runs a distinct-city total over real TCP, matching local semantics" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
const path = try tmp.dir.realpathAlloc(allocator, ".");
defer allocator.free(path);
var db = try testDb(allocator, path);
defer db.close();
try seedAggregateOrders(allocator, &db);
const address = try std.net.Address.parseIp("127.0.0.1", 0);
var server = try Server.init(allocator, &db, address);
try server.start();
defer server.stop();
const client_mod = @import("client.zig");
var client = try client_mod.Client.connect(allocator, server.boundAddress());
defer client.close();
// Sorted by total ascending: krakow/40, warsaw/100, warsaw/250 - distinct
// "city" running count grows 1 (krakow), 2 (warsaw joins), then stays 2
// (warsaw repeats).
const orderBy = [_]querymod.OrderBy{.{ .field = "total", .descending = false }};
const specs = [_]windowmod.WindowSpec{.{ .field = "city", .kind = .count_distinct }};
const results = try client.tableWindow(allocator, "orders", &specs, &.{}, &orderBy, 0, 0, "", .rows);
defer protocol.freeWindowRows(allocator, results);
try std.testing.expectEqual(@as(usize, 3), results.len);
try std.testing.expectEqual(@as(i64, 1), results[0].values[0].int);
try std.testing.expectEqual(@as(i64, 2), results[1].values[0].int);
try std.testing.expectEqual(@as(i64, 2), results[2].values[0].int);
}
test "server table_window applies the expr filter before annotating, over real TCP" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
const path = try tmp.dir.realpathAlloc(allocator, ".");
defer allocator.free(path);
var db = try testDb(allocator, path);
defer db.close();
try seedAggregateOrders(allocator, &db);
const address = try std.net.Address.parseIp("127.0.0.1", 0);
var server = try Server.init(allocator, &db, address);
try server.start();
defer server.stop();
const client_mod = @import("client.zig");
var client = try client_mod.Client.connect(allocator, server.boundAddress());
defer client.close();
const specs = [_]windowmod.WindowSpec{.{ .field = "", .kind = .count }};
const results = try client.tableWindow(allocator, "orders", &specs, &.{}, &.{}, 0, 0, "city eq s:warsaw", .rows);
defer protocol.freeWindowRows(allocator, results);
try std.testing.expectEqual(@as(usize, 2), results.len);
for (results) |wr| try std.testing.expectEqual(@as(i64, 2), wr.values[0].int);
}
test "server table_window reports a malformed expr as bad_request, not a crash" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
const path = try tmp.dir.realpathAlloc(allocator, ".");
defer allocator.free(path);