Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/backend/conat/test/sync/dko.test.ts
1451 views
1
/*
2
Testing basic ops with dko = distributed key:object store with SPARSE updates.
3
4
DEVELOPMENT:
5
6
pnpm test ./dko.test.ts
7
8
*/
9
10
import { dko as createDko } from "@cocalc/backend/conat/sync";
11
import {
12
before,
13
after,
14
connect,
15
client,
16
} from "@cocalc/backend/conat/test/setup";
17
import { wait } from "@cocalc/backend/conat/test/util";
18
19
beforeAll(before);
20
21
describe("create a public dko and do a basic operation", () => {
22
let kv;
23
const name = `test-${Math.random()}`;
24
25
it("creates the dko", async () => {
26
kv = await createDko({ name });
27
expect(kv.getAll()).toEqual({});
28
});
29
30
it("tries to add a non-object and fails", () => {
31
expect(() => {
32
kv.a = 10;
33
}).toThrow("must be objects");
34
});
35
36
it("adds a key to the dko", () => {
37
kv.a = { a: 5, b: 7 };
38
expect(kv.a).toEqual({ a: 5, b: 7 });
39
});
40
41
it("waits for the dko to be saved, then closing and recreates the kv and verifies that the key is there.", async () => {
42
await kv.save();
43
kv.close();
44
kv = await createDko({ name });
45
expect(kv.a).toEqual({ a: 5, b: 7 });
46
});
47
48
it("verifies sparseness of underlying storage", () => {
49
expect(Object.keys(kv.getAll()).length).toBe(1);
50
// 3 = object structure (1) + values (2)
51
expect(Object.keys(kv.dkv.getAll()).length).toBe(3);
52
});
53
54
it("clears and closes the kv", async () => {
55
kv.clear();
56
await kv.close();
57
expect(kv.getAll).toThrow("closed");
58
});
59
});
60
61
describe("create dko and check more complicated keys", () => {
62
let kv;
63
const name = `test-${Math.random()}`;
64
65
it("creates the dko", async () => {
66
kv = await createDko({ name });
67
expect(kv.getAll()).toEqual({});
68
const key = "a!@#$%^&*|()lkasdjfxxxxxxxxxx";
69
kv.set(key, { [key]: "bar" });
70
expect(kv.get(key)).toEqual({ [key]: "bar" });
71
});
72
73
it("clears and closes the kv", async () => {
74
kv.clear();
75
await kv.close();
76
});
77
});
78
79
describe("test a large value that requires chunking", () => {
80
let kv;
81
const name = `test-${Math.random()}`;
82
83
let maxPayload = 0;
84
85
it("sanity check on the max payload", async () => {
86
const client = connect();
87
await wait({ until: () => client.info != null });
88
maxPayload = client.info?.max_payload ?? 0;
89
expect(maxPayload).toBeGreaterThan(500000);
90
});
91
92
it("creates the dko", async () => {
93
kv = await createDko({ name });
94
expect(kv.getAll()).toEqual({});
95
96
const big = { foo: "b".repeat(maxPayload * 1.3) };
97
kv.set("big", big);
98
expect(kv.get("big")).toEqual(big);
99
});
100
101
it("clears and closes the kv", async () => {
102
kv.clear();
103
await kv.close();
104
});
105
});
106
107
describe("test keys that start with a bracket, weird keys, valid JSON, etc", () => {
108
let kv, kv2;
109
let client2;
110
const BAD_KEYS = [
111
"[foo]",
112
"[P] [W}\\ test]",
113
"normal",
114
JSON.stringify(["foo", "bar"]),
115
];
116
it("creates a dko", async () => {
117
client2 = connect();
118
const name = "[!nuts$##&^$$#!\\blah]";
119
kv = await client.sync.dko({ name });
120
kv2 = await client2.sync.dko({ name });
121
for (const key of BAD_KEYS) {
122
kv.set(key, { cocalc: "conat" });
123
expect(kv.has(key)).toBe(true);
124
expect(kv.get(key)).toEqual({ cocalc: "conat" });
125
await kv.save();
126
await wait({ until: () => kv2.has(key) });
127
expect(kv2.get(key)).toEqual({ cocalc: "conat" });
128
}
129
kv.close();
130
kv2.close();
131
});
132
});
133
134
describe("illustrate that https://github.com/sagemathinc/cocalc/issues/8386 is not truly fixed", () => {
135
it("creates a dko", async () => {
136
const kv = await client.sync.dko({ name: "issue-8386" });
137
const key = JSON.stringify(["key", "field"]);
138
kv.set(key, { foo: "bar" });
139
expect(kv.fromPath(key)).toEqual({ key: "key", field: "field" });
140
expect(kv.get(key)).toEqual({ foo: "bar" });
141
142
// here's the bug -- basically if you have a key that is a valid JSON array of
143
// length two (and only then), you get an extra spurious key. This might never
144
// be a problem in practice though, since the key you want is also there.
145
expect(kv.getAll()).toEqual({
146
key: { field: ["foo"] },
147
'["key","field"]': { foo: "bar" },
148
});
149
});
150
});
151
152
afterAll(after);
153
154