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
75
76
77
78
/* Unit tests: Accounting DO with REAL SQLite (node:sqlite) behind a tiny
adapter matching the Workers `state.storage.sql` API. Run: node --test test/accounting.test.js */
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { Accounting } from '../src/accounting.js';
import { makeSqliteState } from './sqlite-adapter.mjs';
const fresh = () => new Accounting(makeSqliteState(), {});
test('create + validate ok', async () => {
const a = fresh();
const u = await a.createUser({ name: 'مامان', quotaGB: 10, expiryDays: 30 });
assert.ok(u.uuid);
const v = await a.validate({ uuid: u.uuid });
assert.deepEqual(v, { ok: true });
});
test('unknown user rejected', async () => {
const a = fresh();
const v = await a.validate({ uuid: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890' });
assert.equal(v.ok, false); assert.equal(v.reason, 'unknown-user');
});
test('quota enforcement', async () => {
const a = fresh();
const u = await a.createUser({ name: 't', quotaGB: 0.001 }); // ~1MB
assert.deepEqual(await a.validate({ uuid: u.uuid }), { ok: true });
const r1 = await a.addUsage({ uuid: u.uuid, up: 600_000, down: 600_000 }); // 1.2MB > quota
assert.equal(r1.overQuota, true);
const v = await a.validate({ uuid: u.uuid });
assert.equal(v.ok, false); assert.equal(v.reason, 'quota-exceeded');
});
test('usage accumulates', async () => {
const a = fresh();
const u = await a.createUser({ name: 't2', quotaGB: 10 });
await a.addUsage({ uuid: u.uuid, up: 100, down: 200 });
await a.addUsage({ uuid: u.uuid, up: 50, down: 50 });
const [row] = await a.listUsers();
assert.equal(row.usedTotal, 400);
});
test('expiry enforced', async () => {
const state = makeSqliteState();
const a = new Accounting(state, {});
const u = await a.createUser({ name: 'tmp', expiryDays: 30 });
assert.deepEqual(await a.validate({ uuid: u.uuid }), { ok: true });
state.storage.sql.exec('UPDATE users SET expires_at = ? WHERE uuid = ?', Date.now() - 1000, u.uuid);
const v = await a.validate({ uuid: u.uuid });
assert.equal(v.ok, false); assert.equal(v.reason, 'expired');
});
test('revoke + reset', async () => {
const a = fresh();
const u = await a.createUser({ name: 'x', quotaGB: 10 });
await a.addUsage({ uuid: u.uuid, up: 10, down: 10 });
await a.revokeUser({ uuid: u.uuid });
const v = await a.validate({ uuid: u.uuid });
assert.equal(v.reason, 'revoked');
await a.resetUsage({ uuid: u.uuid });
const [row] = await a.listUsers();
assert.equal(row.usedTotal, 0);
});
test('fetch RPC routing', async () => {
const a = fresh();
const mk = (method, body) => new Request('http://do/' + method,
{ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body || {}) });
let r = await a.fetch(mk('createUser', { name: 'rpc', quotaGB: 5 }));
let j = await r.json();
assert.equal(j.ok, true);
const uuid = j.result.uuid;
r = await a.fetch(mk('validate', { uuid }));
j = await r.json();
assert.deepEqual(j.result, { ok: true });
r = await a.fetch(mk('nope', {}));
assert.equal(r.status, 404);
});