mirror of
https://github.com/denoland/std.git
synced 2024-11-22 04:59:05 +00:00
106 lines
3.0 KiB
TypeScript
106 lines
3.0 KiB
TypeScript
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||
|
import { TtlCache } from "./ttl_cache.ts";
|
||
|
import { assertEquals } from "@std/assert";
|
||
|
import { FakeTime } from "@std/testing/time";
|
||
|
|
||
|
const UNSET = Symbol("UNSET");
|
||
|
|
||
|
// check `has()`, `get()`, `forEach()`
|
||
|
function assertEntries<K, V>(
|
||
|
cache: TtlCache<K, V>,
|
||
|
entries: [key: K, value: V | typeof UNSET][],
|
||
|
) {
|
||
|
for (const [key, value] of entries) {
|
||
|
assertEquals(cache.has(key), value !== UNSET);
|
||
|
assertEquals(cache.get(key), value === UNSET ? undefined : value);
|
||
|
}
|
||
|
|
||
|
cache.forEach((v, k) => assertEquals(v, entries.find(([x]) => x === k)![1]));
|
||
|
assertContentfulEntries(cache, entries.filter(([, v]) => v !== UNSET));
|
||
|
}
|
||
|
|
||
|
// check `size`, `entries()`, `keys()`, `values()`, `[Symbol.iterator]()`
|
||
|
function assertContentfulEntries<K, V>(
|
||
|
cache: TtlCache<K, V>,
|
||
|
entries: [key: K, value: V][],
|
||
|
) {
|
||
|
const keys = entries.map(([key]) => key);
|
||
|
const values = entries.map(([, value]) => value);
|
||
|
|
||
|
assertEquals(cache.size, entries.length);
|
||
|
|
||
|
assertEquals([...cache.entries()], entries);
|
||
|
assertEquals([...cache.keys()], keys);
|
||
|
assertEquals([...cache.values()], values);
|
||
|
assertEquals([...cache], entries);
|
||
|
}
|
||
|
|
||
|
Deno.test("TtlCache deletes entries", async (t) => {
|
||
|
await t.step("after the default TTL, passed in constructor", () => {
|
||
|
using time = new FakeTime(0);
|
||
|
|
||
|
const cache = new TtlCache<number, string>(10);
|
||
|
|
||
|
cache.set(1, "one");
|
||
|
cache.set(2, "two");
|
||
|
|
||
|
time.now = 1;
|
||
|
assertEntries(cache, [[1, "one"], [2, "two"]]);
|
||
|
|
||
|
time.now = 5;
|
||
|
assertEntries(cache, [[1, "one"], [2, "two"]]);
|
||
|
// setting again resets TTL countdown for key 1
|
||
|
cache.set(1, "one");
|
||
|
|
||
|
time.now = 10;
|
||
|
assertEntries(cache, [[1, "one"], [2, UNSET]]);
|
||
|
|
||
|
time.now = 15;
|
||
|
assertEntries(cache, [[1, UNSET], [2, UNSET]]);
|
||
|
});
|
||
|
|
||
|
await t.step("after a custom TTL, passed in set()", () => {
|
||
|
using time = new FakeTime(0);
|
||
|
|
||
|
const cache = new TtlCache<number, string>(10);
|
||
|
|
||
|
cache.set(1, "one");
|
||
|
cache.set(2, "two", 3);
|
||
|
|
||
|
time.now = 1;
|
||
|
assertEntries(cache, [[1, "one"], [2, "two"]]);
|
||
|
|
||
|
time.now = 3;
|
||
|
assertEntries(cache, [[1, "one"], [2, UNSET]]);
|
||
|
|
||
|
time.now = 10;
|
||
|
assertEntries(cache, [[1, UNSET], [2, UNSET]]);
|
||
|
});
|
||
|
|
||
|
await t.step("after manually calling delete()", () => {
|
||
|
const cache = new TtlCache<number, string>(10);
|
||
|
|
||
|
cache.set(1, "one");
|
||
|
assertEntries(cache, [[1, "one"]]);
|
||
|
assertEquals(cache.delete(1), true);
|
||
|
assertEntries(cache, [[1, UNSET]]);
|
||
|
assertEquals(cache.delete(1), false);
|
||
|
assertEntries(cache, [[1, UNSET]]);
|
||
|
});
|
||
|
|
||
|
await t.step("after manually calling clear()", () => {
|
||
|
const cache = new TtlCache<number, string>(10);
|
||
|
|
||
|
cache.set(1, "one");
|
||
|
assertEntries(cache, [[1, "one"]]);
|
||
|
cache.clear();
|
||
|
assertEntries(cache, [[1, UNSET]]);
|
||
|
});
|
||
|
|
||
|
// this test will fail with `error: Leaks detected` if the timeouts are not cleared
|
||
|
await t.step("[Symbol.dispose]() clears all remaining timeouts", () => {
|
||
|
using cache = new TtlCache<number, string>(10);
|
||
|
cache.set(1, "one");
|
||
|
});
|
||
|
});
|