feat: extend repl
This commit is contained in:
1 parent
dce1077708
commit
aead324484
1 file changed
+156
+156
@@ -2512,3 +2512,159 @@ test "table writes made before commit are not visible to an independent Table ha
|
||||
try std.testing.expectEqualStrings("alice", row.get("name").?.text);
|
||||
}
|
||||
|
||||
test "table put/get/del outside a transaction autocommit immediately like plain Table" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
var repl = Repl.init(allocator, &db);
|
||||
defer repl.deinit();
|
||||
|
||||
const out = try runScript(
|
||||
allocator,
|
||||
&repl,
|
||||
"table put widgets 7 sku=s:ABC qty=i:3\ntable get widgets 7\ntable del widgets 7\ntable get widgets 7\n",
|
||||
);
|
||||
defer allocator.free(out);
|
||||
try std.testing.expect(std.mem.startsWith(u8, out, "OK\n"));
|
||||
try std.testing.expect(std.mem.indexOf(u8, out, "sku=ABC") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, out, "qty=3") != null);
|
||||
try std.testing.expect(std.mem.endsWith(u8, out, "(nil)\n"));
|
||||
}
|
||||
|
||||
test "malformed field is rejected before staging, transaction stays usable" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
var repl = Repl.init(allocator, &db);
|
||||
defer repl.deinit();
|
||||
|
||||
const out = try runScript(
|
||||
allocator,
|
||||
&repl,
|
||||
"begin\ntable put accounts 1 badfieldnoequals\ntable put accounts 1 name=bob\ncommit\ntable get accounts 1\n",
|
||||
);
|
||||
defer allocator.free(out);
|
||||
try std.testing.expect(std.mem.startsWith(u8, out, "OK\nerror: InvalidField\nOK\nOK\n"));
|
||||
try std.testing.expect(std.mem.indexOf(u8, out, "name=bob") != null);
|
||||
}
|
||||
|
||||
test "a real external conflict surfaces error.Conflict on commit and applies nothing" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
try db.put("balance", "100");
|
||||
|
||||
var repl = Repl.init(allocator, &db);
|
||||
defer repl.deinit();
|
||||
|
||||
var stream = std.io.fixedBufferStream("begin\nget balance\n");
|
||||
var out = std.ArrayList(u8).init(allocator);
|
||||
defer out.deinit();
|
||||
try repl.runFromReader(stream.reader(), out.writer(), false);
|
||||
|
||||
try db.put("balance", "external");
|
||||
|
||||
var stream2 = std.io.fixedBufferStream("put balance 150\ncommit\n");
|
||||
try repl.runFromReader(stream2.reader(), out.writer(), false);
|
||||
try std.testing.expect(std.mem.endsWith(u8, out.items, "OK\nerror: Conflict\n"));
|
||||
|
||||
const current = (try db.get(allocator, "balance")).?;
|
||||
defer allocator.free(current);
|
||||
try std.testing.expectEqualStrings("external", current);
|
||||
try std.testing.expect(repl.inTransaction());
|
||||
|
||||
var stream3 = std.io.fixedBufferStream("rollback\n");
|
||||
try repl.runFromReader(stream3.reader(), out.writer(), false);
|
||||
try std.testing.expect(!repl.inTransaction());
|
||||
}
|
||||
|
||||
test "scan always reflects committed Db state, not an in-flight transaction's staged writes" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
var repl = Repl.init(allocator, &db);
|
||||
defer repl.deinit();
|
||||
|
||||
const out = try runScript(allocator, &repl, "put k1 v1\nbegin\nput k2 v2\nscan k\n");
|
||||
defer allocator.free(out);
|
||||
try std.testing.expectEqualStrings("OK\nOK\nOK\nk1\tv1\n", out);
|
||||
}
|
||||
|
||||
test "abandoning an open transaction on deinit frees staged writes and pending TableTxn state" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
var repl = Repl.init(allocator, &db);
|
||||
const out = try runScript(allocator, &repl, "begin\nput a 1\ntable put accounts 1 name=alice\n");
|
||||
defer allocator.free(out);
|
||||
try std.testing.expectEqualStrings("OK\nOK\nOK\n", out);
|
||||
repl.deinit();
|
||||
|
||||
try std.testing.expectEqual(@as(?[]u8, null), try db.get(allocator, "a"));
|
||||
var table = try Table.open(&db, allocator, "accounts");
|
||||
defer table.deinit();
|
||||
try std.testing.expectEqual(@as(?Row, null), try table.get(.{ .text = "1" }));
|
||||
}
|
||||
|
||||
test "flush and compact run against the live Db and stats reflects it" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
var repl = Repl.init(allocator, &db);
|
||||
defer repl.deinit();
|
||||
|
||||
const out = try runScript(allocator, &repl, "put a 1\nflush\ncompact\nstats\n");
|
||||
defer allocator.free(out);
|
||||
try std.testing.expect(std.mem.startsWith(u8, out, "OK\nOK\nOK\n"));
|
||||
try std.testing.expect(out.len > "OK\nOK\nOK\n".len);
|
||||
}
|
||||
|
||||
test "help lists commands without touching db state" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
var repl = Repl.init(allocator, &db);
|
||||
defer repl.deinit();
|
||||
|
||||
const out = try runScript(allocator, &repl, "help\n");
|
||||
defer allocator.free(out);
|
||||
try std.testing.expect(std.mem.indexOf(u8, out, "begin / commit / rollback") != null);
|
||||
}
|
||||
|
||||
test "prompt is written before each read only when requested" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
var repl = Repl.init(allocator, &db);
|
||||
defer repl.deinit();
|
||||
|
||||
var stream = std.io.fixedBufferStream("begin\nput a 1\n");
|
||||
var out = std.ArrayList(u8).init(allocator);
|
||||
defer out.deinit();
|
||||
try repl.runFromReader(stream.reader(), out.writer(), true);
|
||||
try std.testing.expectEqualStrings("cobalt> OK\ncobalt(txn)> OK\ncobalt(txn)> ", out.items);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user