1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { mainReference } from "https://esm.town/v/karfau/mainReference";
import { dlock as dlock2 } from "https://esm.town/v/karfau/dlock";
import { testRunner } from "https://esm.town/v/karfau/testRunner";
export const test_dlock = await testRunner(
{
val: ["karfau", "dlock"],
dlock: dlock2,
get deadline() {
return Math.floor(Date.now() / 1000 + 1);
},
id: mainReference(({ userHandle, valName }) =>
`val_town-${userHandle}-${valName}`
),
ttl: 1,
fetchStub:
(data = {}, { status = 200, ok = status < 400 } = {}) => async () =>
Promise.resolve({ ok, status, json: async () => data } as const),
throwingFetchStub: async () => {
throw new Error("sync from test_dlock::throwingFetchStub");
},
...await import("https://deno.land/std/assert/mod.ts"),
...await import("https://deno.land/std/testing/mock.ts"),
} as const,
async function should_reject_after_last_attempt(
{
dlock,
id,
ttl,
throwingFetchStub,
assertEquals,
assertRejects,
assertSpyCall,
assertSpyCalls,
spy,
},
) {
const fetchSpy = spy(throwingFetchStub);
const err = await assertRejects(() => dlock({ id, ttl }, fetchSpy));
assertEquals(err.message, "sync from test_dlock::throwingFetchStub");
assertSpyCalls(fetchSpy, 5);
assertSpyCall(fetchSpy, 4, {
args: [`https://dlock.univalent.net/lock/${id}/aquire?ttl=${ttl}`],
});
},
async function should_reject_ttl_of_0(
{ dlock, id, ttl, fetchStub, assertMatch, assertRejects },
) {
const err = await assertRejects(() => dlock({ id, ttl: 0 }, fetchStub()));
assertMatch(err.message, /ttl/);
},
async function should_return_lock_on_successful_request(
{ dlock, deadline, fetchStub, assertFalse, assertEquals },
) {
const lease = 375;
const lock = await dlock({}, fetchStub({ lease, deadline }));
assertEquals(lock.lease, lease, "lease");
assertEquals(lock.deadline, deadline, "deadline");
// ideally it should be "val_town-karfau-test_dlock"
// see https://discord.com/channels/1020432421243592714/1143386413748994143
assertEquals(lock.id, "val_town-karfau-testRunner", "id");
assertFalse(lock.isExpired(), "isExpired");
},
// runs into endless loop!
async function skip_should_reject_when_id_is_locked(
{ dlock, id, ttl, deadline, fetchStub, assertRejects, assertEquals },
) {
const error = "lock is acquired by another client";
const err = await assertRejects(() =>
dlock({ id, ttl }, fetchStub({ error, deadline }, { status: 409 }))
);
assertEquals(err.message, error);
},
);
👆 This is a val. Vals are TypeScript snippets of code, written in the browser and run on our servers. Create scheduled functions, email yourself, and persist small pieces of data — all from the browser.