1package simplelru
2
3import "testing"
4
5func TestLRU(t *testing.T) {
6	evictCounter := 0
7	onEvicted := func(k interface{}, v interface{}) {
8		if k != v {
9			t.Fatalf("Evict values not equal (%v!=%v)", k, v)
10		}
11		evictCounter++
12	}
13	l, err := NewLRU(128, onEvicted)
14	if err != nil {
15		t.Fatalf("err: %v", err)
16	}
17
18	for i := 0; i < 256; i++ {
19		l.Add(i, i)
20	}
21	if l.Len() != 128 {
22		t.Fatalf("bad len: %v", l.Len())
23	}
24
25	if evictCounter != 128 {
26		t.Fatalf("bad evict count: %v", evictCounter)
27	}
28
29	for i, k := range l.Keys() {
30		if v, ok := l.Get(k); !ok || v != k || v != i+128 {
31			t.Fatalf("bad key: %v", k)
32		}
33	}
34	for i := 0; i < 128; i++ {
35		_, ok := l.Get(i)
36		if ok {
37			t.Fatalf("should be evicted")
38		}
39	}
40	for i := 128; i < 256; i++ {
41		_, ok := l.Get(i)
42		if !ok {
43			t.Fatalf("should not be evicted")
44		}
45	}
46	for i := 128; i < 192; i++ {
47		ok := l.Remove(i)
48		if !ok {
49			t.Fatalf("should be contained")
50		}
51		ok = l.Remove(i)
52		if ok {
53			t.Fatalf("should not be contained")
54		}
55		_, ok = l.Get(i)
56		if ok {
57			t.Fatalf("should be deleted")
58		}
59	}
60
61	l.Get(192) // expect 192 to be last key in l.Keys()
62
63	for i, k := range l.Keys() {
64		if (i < 63 && k != i+193) || (i == 63 && k != 192) {
65			t.Fatalf("out of order key: %v", k)
66		}
67	}
68
69	l.Purge()
70	if l.Len() != 0 {
71		t.Fatalf("bad len: %v", l.Len())
72	}
73	if _, ok := l.Get(200); ok {
74		t.Fatalf("should contain nothing")
75	}
76}
77
78func TestLRU_GetOldest_RemoveOldest(t *testing.T) {
79	l, err := NewLRU(128, nil)
80	if err != nil {
81		t.Fatalf("err: %v", err)
82	}
83	for i := 0; i < 256; i++ {
84		l.Add(i, i)
85	}
86	k, _, ok := l.GetOldest()
87	if !ok {
88		t.Fatalf("missing")
89	}
90	if k.(int) != 128 {
91		t.Fatalf("bad: %v", k)
92	}
93
94	k, _, ok = l.RemoveOldest()
95	if !ok {
96		t.Fatalf("missing")
97	}
98	if k.(int) != 128 {
99		t.Fatalf("bad: %v", k)
100	}
101
102	k, _, ok = l.RemoveOldest()
103	if !ok {
104		t.Fatalf("missing")
105	}
106	if k.(int) != 129 {
107		t.Fatalf("bad: %v", k)
108	}
109}
110
111// Test that Add returns true/false if an eviction occurred
112func TestLRU_Add(t *testing.T) {
113	evictCounter := 0
114	onEvicted := func(k interface{}, v interface{}) {
115		evictCounter++
116	}
117
118	l, err := NewLRU(1, onEvicted)
119	if err != nil {
120		t.Fatalf("err: %v", err)
121	}
122
123	if l.Add(1, 1) == true || evictCounter != 0 {
124		t.Errorf("should not have an eviction")
125	}
126	if l.Add(2, 2) == false || evictCounter != 1 {
127		t.Errorf("should have an eviction")
128	}
129}
130
131// Test that Contains doesn't update recent-ness
132func TestLRU_Contains(t *testing.T) {
133	l, err := NewLRU(2, nil)
134	if err != nil {
135		t.Fatalf("err: %v", err)
136	}
137
138	l.Add(1, 1)
139	l.Add(2, 2)
140	if !l.Contains(1) {
141		t.Errorf("1 should be contained")
142	}
143
144	l.Add(3, 3)
145	if l.Contains(1) {
146		t.Errorf("Contains should not have updated recent-ness of 1")
147	}
148}
149
150// Test that Peek doesn't update recent-ness
151func TestLRU_Peek(t *testing.T) {
152	l, err := NewLRU(2, nil)
153	if err != nil {
154		t.Fatalf("err: %v", err)
155	}
156
157	l.Add(1, 1)
158	l.Add(2, 2)
159	if v, ok := l.Peek(1); !ok || v != 1 {
160		t.Errorf("1 should be set to 1: %v, %v", v, ok)
161	}
162
163	l.Add(3, 3)
164	if l.Contains(1) {
165		t.Errorf("should not have updated recent-ness of 1")
166	}
167}
168