keys returns a slice of the keys in the cache, from oldest to newest.
Test with a key which is not an atomic value
import std.string : representation; alias Key = immutable(ubyte[]); static struct E { string x; static E undefined() { return E("Not found"); } } alias TestLRU = LRU!(Key, E); uint count; void onEvicted(scope const(Key) key, TestLRU.Element* e) @safe { count++; } auto l = new TestLRU(&onEvicted); Key make_key(size_t num) { return format("data %d", num).representation; } enum N = 4; foreach (i; 0 .. N) { auto key = make_key(i); auto e = E(i.to!string); l[key] = e; } assert(l[make_key(N)] == E.undefined); assert(l[make_key(N - 1)] != E.undefined); assert(l.length == N); assert(l.remove(make_key(2))); assert(count == 1); assert(l.length == N - 1); assert(l[make_key(2)] == E.undefined); // alias TestSyncLRU = SyncLRU!(Key, E);
update/upsert test
alias LRU!(int, int) TestLRU; uint evictCounter; void onEvicted(scope const(int) i, TestLRU.Element* e) @safe { assert(e.entry.key == e.entry.value || e.entry.value == e.entry.key * 7); evictCounter++; } bool ok; auto l = new TestLRU(&onEvicted, 2); int x = 1; ok = l.add(1, x); assert(!ok); assert(evictCounter == 0, "should not have an eviction"); x++; ok = l.add(2, x); assert(!ok); assert(evictCounter == 0, "should still not have an eviction"); ok = l.get(2,x); assert(ok); assert(x == 2, "check inserted"); x = 14; ok = l.update(2,x); assert(ok); ok = l.get(2, x); assert(ok); assert(x == 14, "check updates"); x = 3; ok = l.update(3,x,true); assert(ok); assert(evictCounter == 1, "should have an eviction"); ok = l.get(3, x); assert(ok); assert(x == 3, "check upsert");