UNPKG

@x5e/gink

Version:

an eventually consistent database

361 lines 15.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const test_utils_1 = require("./test_utils"); const implementation_1 = require("../implementation"); const utils_1 = require("../implementation/utils"); it("push to a queue and peek", async function () { // set up the objects for (const store of [ new implementation_1.IndexedDbStore("list-test1", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const queue = await implementation_1.Sequence.create(instance); await queue.push("dummy"); const muid = await queue.push("Hello, World!"); (0, utils_1.ensure)(muid.timestamp > 0); const val = await queue.at(-1); (0, utils_1.ensure)(val === "Hello, World!"); await store.close(); } }); it("push and pop", async function () { // set up the objects for (const store of [ new implementation_1.IndexedDbStore("list-test2", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const list = await implementation_1.Sequence.create(instance); await list.push("A"); await list.push("B"); await list.push("C"); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(), ["A", "B", "C"])); const popped = await list.pop(); (0, utils_1.ensure)(popped === "C"); /* for (const entry of await store.getAllEntries()) { console.log(entry); } for (const exit of await store.getAllExits()) { console.log(exit); } */ const have = JSON.stringify(await list.toArray()); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(), ["A", "B"]), have); const shifted = await list.shift(); (0, utils_1.ensure)(shifted === "A"); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(), ["B"])); const dMuid = await list.push("D"); await list.push("E"); const poppedByMuid = await list.pop(dMuid); (0, utils_1.ensure)(poppedByMuid === "D"); await list.push("F"); await list.push("G"); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(), ["B", "E", "F", "G"])); const poppedByIndex = await list.pop(2); (0, utils_1.ensure)(poppedByIndex === "F"); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(), ["B", "E", "G"])); } }); it("size and at", async function () { // set up the objects for (const store of [ new implementation_1.IndexedDbStore("list-test3", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const list = await implementation_1.Sequence.create(instance); await list.push("A"); await list.push("B"); await list.push("C"); const size = await list.size(); (0, utils_1.ensure)(size === 3); const atEnd = await list.at(-1); (0, utils_1.ensure)(atEnd === "C"); const beginning = await list.at(0); (0, utils_1.ensure)(beginning === "A"); const offEnd = await list.at(-4); (0, utils_1.ensure)(offEnd === undefined); const nearEnd = await list.at(-3); (0, utils_1.ensure)(nearEnd === "A"); await list.pop(); const size2 = await list.size(); (0, utils_1.ensure)(size2 === 2); const second = await list.at(1); (0, utils_1.ensure)(second === "B"); const third = await list.at(3); (0, utils_1.ensure)(third === undefined); } }); it("entries", async function () { // set up the objects for (const store of [ new implementation_1.IndexedDbStore("list-test4", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const list = await implementation_1.Sequence.create(instance); await list.push("A"); await list.push("B"); await list.push("C"); const buffer = []; for await (const [muid, contents] of list.entries()) { const val = await list.pop(muid); (0, utils_1.ensure)(val === contents, `val=${val}, contents=${contents}`); buffer.push(contents); } (0, utils_1.ensure)((0, utils_1.matches)(buffer, ["A", "B", "C"])); } }); it("list-changeset", async function () { for (const store of [ new implementation_1.IndexedDbStore("list-test5", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; let bundler = await instance.startBundle(); const list = await implementation_1.Sequence.create(instance, { bundler }); await list.push("A", { bundler }); await list.push("B", { bundler }); await list.push("C", { bundler }); const info = await bundler.commit(); (0, utils_1.ensure)(info.timestamp !== undefined && info.timestamp > 0); (0, utils_1.ensure)(list.address.timestamp === info.timestamp); for await (const [muid, _] of list.entries()) { (0, utils_1.ensure)(muid.timestamp === info.timestamp); } bundler = await instance.startBundle(); await list.shift(false, { bundler }); await list.push("D", { bundler }); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(), ["A", "B", "C"])); await bundler.commit(); const result = await list.toArray(); (0, utils_1.ensure)((0, utils_1.matches)(result, ["B", "C", "D"])); } }); it("List.toJSON", async function () { // set up the objects for (const store of [ new implementation_1.IndexedDbStore("list-toJSON", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const list = await implementation_1.Sequence.create(instance); await list.push("A"); await list.push(true); await list.push(false); const subList = await implementation_1.Sequence.create(instance); await subList.push(33); await list.push(subList); const subDir = await implementation_1.Directory.create(instance); await subDir.set("cheese", "fries"); await list.push(subDir); const bytes = new Uint8Array(3); bytes[0] = 255; bytes[1] = 94; bytes[2] = 32; await list.push(bytes); const asJson = await list.toJson(); (0, utils_1.ensure)(asJson === `["A",true,false,[33],{"cheese":"fries"},"FF5E20"]`, asJson); } }); it("List.asOf", async function () { // set up the objects for (const store of [ new implementation_1.IndexedDbStore("list-asOf", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const list = await implementation_1.Sequence.create(instance); const time0 = Date.now() * 1000; await (0, test_utils_1.sleep)(10); await list.push("A"); await (0, test_utils_1.sleep)(10); const time1 = Date.now() * 1000; await (0, test_utils_1.sleep)(10); await list.push(true); await (0, test_utils_1.sleep)(10); const time2 = Date.now() * 1000; await (0, test_utils_1.sleep)(10); await list.push(false); await (0, test_utils_1.sleep)(10); const time3 = Date.now() * 1000; (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(Infinity, time3), ["A", true, false])); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(Infinity, time2), ["A", true])); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(Infinity, time1), ["A"])); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(Infinity, time0), [])); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(Infinity, -1), ["A", true])); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(Infinity, -2), ["A"])); (0, utils_1.ensure)((0, utils_1.matches)(await list.toArray(Infinity, -3), [])); } }); it("List.clear", async function () { for (const store of [ new implementation_1.IndexedDbStore("list-clear", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const list = await implementation_1.Sequence.create(instance); await list.push("hello"); await list.push("world"); let size = await list.size(); (0, utils_1.ensure)(size === 2); const clearMuid = await list.clear(); size = await list.size(); (0, utils_1.ensure)(size === 0); await list.push("goodbye"); size = await list.size(); (0, utils_1.ensure)(size === 1); size = await list.size(clearMuid.timestamp); (0, utils_1.ensure)(size === 2); await list.clear(true); size = await list.size(clearMuid.timestamp); (0, utils_1.ensure)(size === 0, `size=${size}`); } }); it("List.purge_pop", async function () { for (const store of [ new implementation_1.IndexedDbStore("list-purgePop", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const seq = await implementation_1.Sequence.create(instance); await seq.push("foo"); await seq.push("bar"); const beforeFirstPop = (0, utils_1.generateTimestamp)(); const popped = await seq.pop(); (0, utils_1.ensure)(popped === "bar", `popped=${popped}`); (0, utils_1.ensure)((0, utils_1.matches)(["foo"], await seq.toArray()), (await seq.toArray()).toString()); const previous = await seq.toArray(Infinity, beforeFirstPop); (0, utils_1.ensure)((0, utils_1.matches)(["foo", "bar"], previous), "previous=" + previous.toString()); const shifted = await seq.shift(true); (0, utils_1.ensure)(shifted === "foo"); (0, utils_1.ensure)((0, utils_1.matches)(["bar"], await seq.toArray(Infinity, beforeFirstPop))); } }); it("List.move", async function () { for (const store of [ new implementation_1.IndexedDbStore("list-move", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const seq = await implementation_1.Sequence.create(instance); await seq.push("A"); await (0, test_utils_1.sleep)(100); await seq.push("B"); await (0, test_utils_1.sleep)(100); const cMuid = await seq.push("C"); await seq.push("D"); await (0, test_utils_1.sleep)(100); (0, utils_1.ensure)((await seq.toArray()).toString() === "A,B,C,D"); await seq.move(0, -1); (0, utils_1.ensure)((await seq.toArray()).toString() === "B,C,D,A", (await seq.toArray()).toString()); await seq.move(2, 0); (0, utils_1.ensure)((await seq.toArray()).toString() === "D,B,C,A", (await seq.toArray()).toString()); await seq.move(cMuid, 1); (0, utils_1.ensure)((await seq.toArray()).toString() === "D,C,B,A", (await seq.toArray()).toString()); } }); it("extend", async function () { for (const store of [ new implementation_1.IndexedDbStore("list-extend", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const seq = await implementation_1.Sequence.create(instance); const array = [0, 1, 2, 3, 4, 5, 6]; await seq.extend(array); (0, utils_1.ensure)((await seq.at(0)) === 0); (0, utils_1.ensure)((await seq.at(6)) === 6); const bundler = await instance.startBundle(); const array2 = [7, 8, 9, 10]; await seq.extend(array2, { bundler }); await bundler.commit(); (0, utils_1.ensure)((await seq.at(7)) === 7); (0, utils_1.ensure)((await seq.at(10)) === 10); } }); it("List.reset", async function () { for (const store of [ new implementation_1.IndexedDbStore("list-reset", true), new implementation_1.MemoryStore(true), ]) { const instance = new implementation_1.Database({ store }); await instance.ready; const seq = await implementation_1.Sequence.create(instance); const array = [0, 1, 2, 3, 4, 5, 6]; await seq.extend(array); (0, utils_1.ensure)((await seq.at(0)) === 0); (0, utils_1.ensure)((await seq.at(6)) === 6); const afterExtend = (0, utils_1.generateTimestamp)(); const array2 = [7, 8, 9]; await seq.extend(array2); (0, utils_1.ensure)((await seq.size()) === 10); const afterSecond = (0, utils_1.generateTimestamp)(); await seq.reset(afterExtend); (0, utils_1.ensure)((await seq.size()) === 7); (0, utils_1.ensure)((await seq.at(0)) === 0); (0, utils_1.ensure)((await seq.at(6)) === 6); await seq.reset(); (0, utils_1.ensure)((await seq.size()) === 0); await seq.reset(afterSecond); (0, utils_1.ensure)((await seq.size()) === 10, (await seq.size()).toString()); (0, utils_1.ensure)((await seq.at(0)) === 0); (0, utils_1.ensure)((await seq.at(9)) === 9); await seq.push(10); await seq.push(11); await seq.move(10, 0); await seq.reset(afterSecond); (0, utils_1.ensure)((await seq.size()) === 10); (0, utils_1.ensure)((await seq.at(0)) === 0); (0, utils_1.ensure)((await seq.at(9)) === 9); await seq.pop(0); (0, utils_1.ensure)((await seq.size()) === 9); await seq.reset(afterSecond); (0, utils_1.ensure)((await seq.size()) === 10); (0, utils_1.ensure)((await seq.at(0)) === 0); (0, utils_1.ensure)((await seq.at(9)) === 9); // Test recursive reset await seq.clear(); const box = await implementation_1.Box.create(instance); const dir = await implementation_1.Directory.create(instance); await box.set(dir); await dir.set("foo", "bar"); await seq.push(box); const afterBox = (0, utils_1.generateTimestamp)(); await dir.set("foo", "baz"); await box.set("changed!"); await seq.push(1); const beforeReset = (0, utils_1.generateTimestamp)(); await seq.reset(afterBox, true); (0, utils_1.ensure)((await seq.size()) === 1); (0, utils_1.ensure)((await box.get()) instanceof implementation_1.Directory); (0, utils_1.ensure)((await dir.get("foo")) === "bar"); // Reset back await seq.reset(beforeReset, true); (0, utils_1.ensure)((await seq.size()) === 2); (0, utils_1.ensure)((await seq.at(1)) === 1); (0, utils_1.ensure)((await box.get()) === "changed!"); // This will not have been reset, since the directory was not held // in the box at the time of the reset (0, utils_1.ensure)((await dir.get("foo")) === "bar"); await seq.shift(); // Remove the box await seq.reset(beforeReset, true); (0, utils_1.ensure)((await seq.size()) === 2); (0, utils_1.ensure)((await seq.at(1)) === 1); (0, utils_1.ensure)((await box.get()) === "changed!"); } }); //# sourceMappingURL=Sequence.test.js.map