feat: fill in repl
This commit is contained in:
1 parent
755c0ece36
commit
dce1077708
1 file changed
+157
+157
@@ -2355,3 +2355,160 @@ test "unknown command and wrong arg counts report errors without crashing" {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "staged writes inside a transaction are invisible until commit, then durable" {
|
||||||
|
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\nput bal 100\nget bal\ncommit\nget bal\n");
|
||||||
|
defer allocator.free(out);
|
||||||
|
try std.testing.expectEqualStrings("OK\nOK\n100\nOK\n100\n", out);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "get mid-transaction steers the next put, applied atomically on commit" {
|
||||||
|
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("bal", "100");
|
||||||
|
|
||||||
|
var repl = Repl.init(allocator, &db);
|
||||||
|
defer repl.deinit();
|
||||||
|
|
||||||
|
const out = try runScript(allocator, &repl, "begin\nget bal\nput bal 150\ncommit\nget bal\n");
|
||||||
|
defer allocator.free(out);
|
||||||
|
try std.testing.expectEqualStrings("OK\n100\nOK\nOK\n150\n", out);
|
||||||
|
|
||||||
|
const stored = (try db.get(allocator, "bal")).?;
|
||||||
|
defer allocator.free(stored);
|
||||||
|
try std.testing.expectEqualStrings("150", stored);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "rollback discards staged writes entirely" {
|
||||||
|
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\nput x 1\nrollback\nget x\n");
|
||||||
|
defer allocator.free(out);
|
||||||
|
try std.testing.expectEqualStrings("OK\nOK\nOK\n(nil)\n", out);
|
||||||
|
try std.testing.expectEqual(@as(?[]u8, null), try db.get(allocator, "x"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "commit/rollback without an active transaction report NoActiveTransaction" {
|
||||||
|
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, "commit\nrollback\nput a 1\nget a\n");
|
||||||
|
defer allocator.free(out);
|
||||||
|
try std.testing.expectEqualStrings(
|
||||||
|
"error: NoActiveTransaction\nerror: NoActiveTransaction\nOK\n1\n",
|
||||||
|
out,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "double begin is rejected and leaves the first transaction 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\nput a 1\nbegin\ncommit\nget a\n");
|
||||||
|
defer allocator.free(out);
|
||||||
|
try std.testing.expectEqualStrings("OK\nOK\nerror: TransactionAlreadyActive\nOK\n1\n", out);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "table put/get/del inside a transaction stage through TableTxn atomically across two tables" {
|
||||||
|
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\n" ++
|
||||||
|
"table put accounts 1 name=alice balance=i:100\n" ++
|
||||||
|
"table put ledger 1 note=opening\n" ++
|
||||||
|
"table get accounts 1\n" ++
|
||||||
|
"commit\n" ++
|
||||||
|
"table get accounts 1\n" ++
|
||||||
|
"table get ledger 1\n",
|
||||||
|
);
|
||||||
|
defer allocator.free(out);
|
||||||
|
|
||||||
|
var lines = std.mem.splitScalar(u8, std.mem.trimRight(u8, out, "\n"), '\n');
|
||||||
|
try std.testing.expectEqualStrings("OK", lines.next().?);
|
||||||
|
try std.testing.expectEqualStrings("OK", lines.next().?);
|
||||||
|
try std.testing.expectEqualStrings("OK", lines.next().?);
|
||||||
|
const preCommitGet = lines.next().?;
|
||||||
|
try std.testing.expect(std.mem.indexOf(u8, preCommitGet, "name=alice") != null);
|
||||||
|
try std.testing.expectEqualStrings("OK", lines.next().?);
|
||||||
|
const postAccounts = lines.next().?;
|
||||||
|
try std.testing.expect(std.mem.indexOf(u8, postAccounts, "balance=100") != null);
|
||||||
|
const postLedger = lines.next().?;
|
||||||
|
try std.testing.expect(std.mem.indexOf(u8, postLedger, "note=opening") != null);
|
||||||
|
try std.testing.expectEqual(@as(?[]const u8, null), lines.next());
|
||||||
|
|
||||||
|
var directTable = try Table.open(&db, allocator, "accounts");
|
||||||
|
defer directTable.deinit();
|
||||||
|
var row = (try directTable.get(.{ .text = "1" })).?;
|
||||||
|
defer row.deinit();
|
||||||
|
try std.testing.expectEqual(@as(i64, 100), row.get("balance").?.int);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "table writes made before commit are not visible to an independent Table handle" {
|
||||||
|
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\ntable put accounts 1 name=alice\n");
|
||||||
|
var out = std.ArrayList(u8).init(allocator);
|
||||||
|
defer out.deinit();
|
||||||
|
try repl.runFromReader(stream.reader(), out.writer(), false);
|
||||||
|
try std.testing.expectEqualStrings("OK\nOK\n", out.items);
|
||||||
|
|
||||||
|
var outsider = try Table.open(&db, allocator, "accounts");
|
||||||
|
defer outsider.deinit();
|
||||||
|
try std.testing.expectEqual(@as(?Row, null), try outsider.get(.{ .text = "1" }));
|
||||||
|
|
||||||
|
try repl.txn.?.commit();
|
||||||
|
repl.discardTxnState();
|
||||||
|
|
||||||
|
var again = try Table.open(&db, allocator, "accounts");
|
||||||
|
defer again.deinit();
|
||||||
|
var row = (try again.get(.{ .text = "1" })).?;
|
||||||
|
defer row.deinit();
|
||||||
|
try std.testing.expectEqualStrings("alice", row.get("name").?.text);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user