@@ -44,3 +44,96 @@ func TestCacheGet(t *testing.T) {
4444 })
4545 }
4646}
47+
48+ func TestCacheAdd (t * testing.T ) {
49+ tests := []struct {
50+ name string
51+ size int
52+ keysToAdd []string
53+ valueToAdd []string
54+ expectedCache buffer [string , string ]
55+ }{
56+ {
57+ "beyond_capacity_evicts_first_untouched" ,
58+ 3 ,
59+ []string {"key-a" , "key-b" , "key-c" , "key-d" , "key-e" },
60+ []string {"val-a" , "val-b" , "val-c" , "val-d" , "val-e" },
61+ buffer [string , string ]{
62+ & bufferItem [string , string ]{key : "key-e" , value : "val-e" },
63+ & bufferItem [string , string ]{key : "key-b" , value : "val-b" },
64+ & bufferItem [string , string ]{key : "key-d" , value : "val-d" },
65+ },
66+ },
67+ {
68+ "multiple_touches_decreases_eviction_chances" ,
69+ 3 ,
70+ []string {"key-a" , "key-b" , "key-c" , "key-a" , "key-a" , "key-d" , "key-e" },
71+ []string {"val-a" , "val-b" , "val-c" , "val-a" , "val-a" , "val-d" , "val-e" },
72+ buffer [string , string ]{
73+ & bufferItem [string , string ]{key : "key-a" , value : "val-a" },
74+ & bufferItem [string , string ]{key : "key-e" , value : "val-e" },
75+ & bufferItem [string , string ]{key : "key-d" , value : "val-d" },
76+ },
77+ },
78+ }
79+ for _ , test := range tests {
80+ t .Run (test .name , func (t * testing.T ) {
81+ cache := New [string , string ](test .size )
82+ for i := 0 ; i < len (test .keysToAdd ); i ++ {
83+ key := test .keysToAdd [i ]
84+ val := test .valueToAdd [i ]
85+ cache .Add (key , val )
86+ }
87+ for i := 0 ; i < len (cache .buf ); i ++ {
88+ cachedKey := cache .buf [i ].key
89+ cachedValue := cache .buf [i ].value
90+ expectedKey := test .expectedCache [i ].key
91+ expectedValue := test .expectedCache [i ].value
92+ if cachedKey != expectedKey {
93+ t .Fatalf ("bad cache key; got %s, wanted %s at index %d" , cachedKey , expectedKey , i )
94+ }
95+ if cachedValue != expectedValue {
96+ t .Fatalf ("bad cache value; got %s, wanted %s at index %d" , cachedValue , expectedValue , i )
97+ }
98+ }
99+ })
100+ }
101+ }
102+
103+ func BenchmarkGetAllHits (b * testing.B ) {
104+ b .ReportAllocs ()
105+ type complexStruct struct {
106+ a , b , c , d , e , f int64
107+ k , l , m , n , o , p float64
108+ }
109+ // Populate the cache
110+ l := New [int , complexStruct ](32 )
111+ for z := 0 ; z < 32 ; z ++ {
112+ l .Add (z , complexStruct {a : int64 (z )})
113+ }
114+
115+ b .ResetTimer ()
116+ for z := 0 ; z < b .N ; z ++ {
117+ // take the lower 5 bits as mod 32 so we always hit
118+ l .Get (z & 31 )
119+ }
120+ }
121+
122+ func BenchmarkGetHalfHits (b * testing.B ) {
123+ b .ReportAllocs ()
124+ type complexStruct struct {
125+ a , b , c , d , e , f int64
126+ k , l , m , n , o , p float64
127+ }
128+ // Populate the cache
129+ l := New [int , complexStruct ](32 )
130+ for z := 0 ; z < 32 ; z ++ {
131+ l .Add (z , complexStruct {a : int64 (z )})
132+ }
133+
134+ b .ResetTimer ()
135+ for z := 0 ; z < b .N ; z ++ {
136+ // take the lower 4 bits as mod 16 shifted left by 1 to
137+ l .Get ((z & 15 )<< 1 | z & 16 >> 4 | z & 1 << 4 )
138+ }
139+ }
0 commit comments