feat: grow server
This commit is contained in:
1 parent
555977be6b
commit
ea08f11a80
1 file changed
+159
+159
@@ -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);
|
||||||
|
|
||||||
Reference in new issue
Block a user