Initial Commit
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
import { CRDT_CODES, CrdtError } from "../../errors/crdt-error.js";
|
||||
import { PNCounter } from "./pn-counter.js";
|
||||
|
||||
describe("PNCounter", () => {
|
||||
it("starts at 0", { timeout: 5000 }, () => {
|
||||
expect(new PNCounter().total()).toBe(0);
|
||||
});
|
||||
|
||||
it("increments", { timeout: 5000 }, () => {
|
||||
const c = new PNCounter();
|
||||
c.increment("n1", 10);
|
||||
expect(c.total()).toBe(10);
|
||||
});
|
||||
|
||||
it("decrements", { timeout: 5000 }, () => {
|
||||
const c = new PNCounter();
|
||||
c.increment("n1", 5);
|
||||
c.decrement("n1", 3);
|
||||
expect(c.total()).toBe(2);
|
||||
});
|
||||
|
||||
it("can go negative", { timeout: 5000 }, () => {
|
||||
const c = new PNCounter();
|
||||
c.decrement("n1", 5);
|
||||
expect(c.total()).toBe(-5);
|
||||
});
|
||||
|
||||
it("throws for zero increment delta", { timeout: 5000 }, () => {
|
||||
expect(() => new PNCounter().increment("n1", 0)).toThrow(CrdtError);
|
||||
});
|
||||
|
||||
it("throws for negative decrement delta", { timeout: 5000 }, () => {
|
||||
expect(() => new PNCounter().decrement("n1", -1)).toThrow(CrdtError);
|
||||
});
|
||||
|
||||
it("decrement throws for zero delta", { timeout: 5000 }, () => {
|
||||
const err = (() => {
|
||||
try {
|
||||
new PNCounter().decrement("n1", 0);
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
})();
|
||||
expect((err as CrdtError).code).toBe(CRDT_CODES.OPERATION_INVALID);
|
||||
});
|
||||
|
||||
it("merge", { timeout: 5000 }, () => {
|
||||
const a = new PNCounter();
|
||||
a.increment("n1", 5);
|
||||
const b = new PNCounter();
|
||||
b.increment("n2", 3);
|
||||
b.decrement("n1", 2);
|
||||
a.merge(b.state());
|
||||
expect(a.total()).toBe(6); // 5+3-2
|
||||
});
|
||||
|
||||
it("toJSON / fromJSON round-trip", { timeout: 5000 }, () => {
|
||||
const a = new PNCounter();
|
||||
a.increment("n1", 10);
|
||||
a.decrement("n1", 4);
|
||||
const b = new PNCounter();
|
||||
b.fromJSON(a.toJSON());
|
||||
expect(b.total()).toBe(6);
|
||||
});
|
||||
|
||||
it("fromJSON throws for invalid type", { timeout: 5000 }, () => {
|
||||
expect(() =>
|
||||
new PNCounter().fromJSON(
|
||||
JSON.stringify({
|
||||
type: "wrong",
|
||||
increments: {},
|
||||
decrements: {},
|
||||
})
|
||||
)
|
||||
).toThrow(CrdtError);
|
||||
});
|
||||
|
||||
it("fromJSON throws for bad JSON", { timeout: 5000 }, () => {
|
||||
expect(() => new PNCounter().fromJSON("bad")).toThrow(CrdtError);
|
||||
});
|
||||
|
||||
it("clone is independent", { timeout: 5000 }, () => {
|
||||
const a = new PNCounter();
|
||||
a.increment("n1", 5);
|
||||
const b = a.clone();
|
||||
b.increment("n1", 10);
|
||||
expect(a.total()).toBe(5);
|
||||
});
|
||||
|
||||
it("value() equals total()", { timeout: 5000 }, () => {
|
||||
const c = new PNCounter();
|
||||
c.increment("n1", 7);
|
||||
expect(c.value()).toBe(c.total());
|
||||
});
|
||||
|
||||
it("default delta=1 for increment", { timeout: 5000 }, () => {
|
||||
const c = new PNCounter();
|
||||
c.increment("n1");
|
||||
expect(c.total()).toBe(1);
|
||||
});
|
||||
|
||||
it("default delta=1 for decrement", { timeout: 5000 }, () => {
|
||||
const c = new PNCounter();
|
||||
c.increment("n1", 5);
|
||||
c.decrement("n1");
|
||||
expect(c.total()).toBe(4);
|
||||
});
|
||||
|
||||
it("merge does not regress lower remote increment", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
const a = new PNCounter();
|
||||
a.increment("n1", 10);
|
||||
const b = new PNCounter();
|
||||
b.increment("n1", 3); // lower than a
|
||||
a.merge(b.state());
|
||||
expect(a.total()).toBe(10); // should not decrease
|
||||
});
|
||||
|
||||
it("merge does not regress lower remote decrement", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
const a = new PNCounter();
|
||||
a.decrement("n1", 10);
|
||||
const b = new PNCounter();
|
||||
b.decrement("n1", 3); // lower than a
|
||||
a.merge(b.state());
|
||||
expect(a.total()).toBe(-10); // should not change
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user