1test("lru basic", () => {
2 const lru = new Lru({ capacity: 3 });
3 lru.set("a", 1);
4 lru.set("b", 2);
5 lru.set("c", 3);
6 assert.deepEqual(lru.serialize(), [
7 ["c", 3, 1],
8 ["b", 2, 1],
9 ["a", 1, 1],
10 ]);
11 lru.set("d", 4); // deletes `a`
12 assert.deepEqual(lru.serialize(), [
13 ["d", 4, 1],
14 ["c", 3, 1],
15 ["b", 2, 1],
16 ]);
17 lru.set("c", 5);
18 lru.get("b");
19 lru.set("e", 6);
20 assert.deepEqual(lru.serialize(), [
21 ["e", 6, 1],
22 ["b", 2, 1],
23 ["c", 5, 1],
24 ]);
25 lru.capacity = 10;
26 lru.set("a", -1);
27 lru.set("a", 0);
28 lru.set("z", 1);
29 lru.set("x", 1);
30 lru.set("w", 1);
31 assert.deepEqual(lru.serialize(), [
32 ["w", 1, 1],
33 ["x", 1, 1],
34 ["z", 1, 1],
35 ["a", 0, 1],
36 ["e", 6, 1],
37 ["b", 2, 1],
38 ["c", 5, 1],
39 ]);
40 lru.delete("a");
41 assert.deepEqual(lru.serialize(), [
42 ["w", 1, 1],
43 ["x", 1, 1],
44 ["z", 1, 1],
45 ["e", 6, 1],
46 ["b", 2, 1],
47 ["c", 5, 1],
48 ]);
49 lru.capacity = 2;
50 assert.deepEqual(lru.serialize(), [
51 ["w", 1, 1],
52 ["x", 1, 1],
53 ]);
54 lru.ensureUnusedCapacity(1);
55 assert.deepEqual(lru.serialize(), [
56 ["w", 1, 1],
57 ]);
58 lru.ensureUnusedCapacity(1.2);
59 assert.deepEqual(lru.serialize(), []);
60 lru.ensureUnusedCapacity(2);
61});
62test("lru sized elements", () => {
63 const lru = new Lru<string, number>({ capacity: 10, sizeFn: (v) => v });
64 lru.set("a", 3);
65 lru.set("b", 3);
66 lru.set("c", 3);
67 assert.deepEqual(lru.serialize(), [
68 ["c", 3, 3],
69 ["b", 3, 3],
70 ["a", 3, 3],
71 ]);
72 // hitting exact capacity
73 lru.set("d", 1);
74 lru.set("d", 1);
75 assert.deepEqual(lru.serialize(), [
76 ["d", 1, 1],
77 ["c", 3, 3],
78 ["b", 3, 3],
79 ["a", 3, 3],
80 ]);
81 lru.set("e", 1);
82 assert.deepEqual(lru.serialize(), [
83 ["e", 1, 1],
84 ["d", 1, 1],
85 ["c", 3, 3],
86 ["b", 3, 3],
87 ]);
88 lru.clear();
89 lru.set("a", 3);
90 lru.set("b", 3);
91 lru.set("c", 3);
92 lru.set("d", 1);
93 lru.get("a");
94 lru.get("b");
95 lru.get("c");
96 lru.set("e", 1);
97 assert.deepEqual(lru.serialize(), [
98 ["e", 1, 1],
99 ["c", 3, 3],
100 ["b", 3, 3],
101 ["a", 3, 3],
102 ]);
103});
104test("lru throw on exceeding capacity", () => {
105 const lru = new Lru<string, number>({ capacity: 1, sizeFn: (v) => v });
106 lru.set("e", 1);
107 lru.set("e", 1);
108 assert.throws(() => lru.set("e", 2), RangeError);
109 assert.throws(() => lru.set("d", 2), RangeError);
110 lru.set("d", 1);
111});
112test("locked items cannot be evicted", () => {
113 const lru = new Lru<string, number>({ capacity: 3, sizeFn: (v) => v });
114 lru.set("e", 1);
115 lru.set("d", 1);
116 lru.set("f", 1);
117
118 const unlock = lru.lock("e");
119 lru.ensureUnusedCapacity(2);
120 assert.deepEqual(lru.serialize(), [
121 ["e", 1, 1],
122 ]);
123
124 unlock();
125
126 lru.ensureUnusedCapacity(3);
127
128 assert.deepEqual(lru.serialize(), []);
129});
130test("throws on evicting a locked item", () => {
131 const lru = new Lru<string, number>({ capacity: 3, sizeFn: (v) => v });
132 lru.set("e", 1);
133 void lru.lock("e");
134 assert.throws(() => lru.ensureUnusedCapacity(3), RangeError);
135});
136test("revival", () => {
137 let lru = new Lru<string, number>({ capacity: 3, sizeFn: (v) => 1 });
138 lru.set("a", 1);
139 lru.set("b", 2);
140 lru.set("c", 3);
141 lru.set("d", 4);
142 const state = lru.serialize();
143 lru = new Lru({ capacity: 3, sizeFn: (v) => 1 });
144 lru.revive(state);
145 assert.equal(lru.get("c"), 3);
146 assert.equal(lru.get("a"), undefined);
147 lru.set("e", 5);
148 assert.equal(lru.get("d"), 4);
149 assert.equal(lru.get("e"), 5);
150});
151
152import assert from "node:assert";
153import { test } from "vitest";
154import { Lru } from "./Lru.ts";