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();
|
||||
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