1
16
17 package cache
18
19 import (
20 "fmt"
21 "strings"
22 "testing"
23
24 "github.com/google/go-cmp/cmp"
25 "github.com/stretchr/testify/assert"
26 )
27
28 func TestThreadSafeStoreDeleteRemovesEmptySetsFromIndex(t *testing.T) {
29 testIndexer := "testIndexer"
30
31 indexers := Indexers{
32 testIndexer: func(obj interface{}) (strings []string, e error) {
33 indexes := []string{obj.(string)}
34 return indexes, nil
35 },
36 }
37
38 indices := Indices{}
39 store := NewThreadSafeStore(indexers, indices).(*threadSafeMap)
40
41 testKey := "testKey"
42
43 store.Add(testKey, testKey)
44
45
46 set := store.index.indices[testIndexer][testKey]
47
48 if len(set) != 1 {
49 t.Errorf("Initial assumption of index backing string set having 1 element failed. Actual elements: %d", len(set))
50 return
51 }
52
53 store.Delete(testKey)
54 set, present := store.index.indices[testIndexer][testKey]
55
56 if present {
57 t.Errorf("Index backing string set not deleted from index. Set length: %d", len(set))
58 }
59 }
60
61 func TestThreadSafeStoreAddKeepsNonEmptySetPostDeleteFromIndex(t *testing.T) {
62 testIndexer := "testIndexer"
63 testIndex := "testIndex"
64
65 indexers := Indexers{
66 testIndexer: func(obj interface{}) (strings []string, e error) {
67 indexes := []string{testIndex}
68 return indexes, nil
69 },
70 }
71
72 indices := Indices{}
73 store := NewThreadSafeStore(indexers, indices).(*threadSafeMap)
74
75 store.Add("retain", "retain")
76 store.Add("delete", "delete")
77
78
79 set := store.index.indices[testIndexer][testIndex]
80
81 if len(set) != 2 {
82 t.Errorf("Initial assumption of index backing string set having 2 elements failed. Actual elements: %d", len(set))
83 return
84 }
85
86 store.Delete("delete")
87 set, present := store.index.indices[testIndexer][testIndex]
88
89 if !present {
90 t.Errorf("Index backing string set erroneously deleted from index.")
91 return
92 }
93
94 if len(set) != 1 {
95 t.Errorf("Index backing string set has incorrect length, expect 1. Set length: %d", len(set))
96 }
97 }
98
99 func TestThreadSafeStoreIndexingFunctionsWithMultipleValues(t *testing.T) {
100 testIndexer := "testIndexer"
101
102 indexers := Indexers{
103 testIndexer: func(obj interface{}) ([]string, error) {
104 return strings.Split(obj.(string), ","), nil
105 },
106 }
107
108 indices := Indices{}
109 store := NewThreadSafeStore(indexers, indices).(*threadSafeMap)
110
111 store.Add("key1", "foo")
112 store.Add("key2", "bar")
113
114 assert := assert.New(t)
115
116 compare := func(key string, expected []string) error {
117 values := store.index.indices[testIndexer][key].List()
118 if cmp.Equal(values, expected) {
119 return nil
120 }
121 return fmt.Errorf("unexpected index for key %s, diff=%s", key, cmp.Diff(values, expected))
122 }
123
124 assert.NoError(compare("foo", []string{"key1"}))
125 assert.NoError(compare("bar", []string{"key2"}))
126
127 store.Update("key2", "foo,bar")
128
129 assert.NoError(compare("foo", []string{"key1", "key2"}))
130 assert.NoError(compare("bar", []string{"key2"}))
131
132 store.Update("key1", "foo,bar")
133
134 assert.NoError(compare("foo", []string{"key1", "key2"}))
135 assert.NoError(compare("bar", []string{"key1", "key2"}))
136
137 store.Add("key3", "foo,bar,baz")
138
139 assert.NoError(compare("foo", []string{"key1", "key2", "key3"}))
140 assert.NoError(compare("bar", []string{"key1", "key2", "key3"}))
141 assert.NoError(compare("baz", []string{"key3"}))
142
143 store.Update("key1", "foo")
144
145 assert.NoError(compare("foo", []string{"key1", "key2", "key3"}))
146 assert.NoError(compare("bar", []string{"key2", "key3"}))
147 assert.NoError(compare("baz", []string{"key3"}))
148
149 store.Update("key2", "bar")
150
151 assert.NoError(compare("foo", []string{"key1", "key3"}))
152 assert.NoError(compare("bar", []string{"key2", "key3"}))
153 assert.NoError(compare("baz", []string{"key3"}))
154
155 store.Delete("key1")
156
157 assert.NoError(compare("foo", []string{"key3"}))
158 assert.NoError(compare("bar", []string{"key2", "key3"}))
159 assert.NoError(compare("baz", []string{"key3"}))
160
161 store.Delete("key3")
162
163 assert.NoError(compare("foo", []string{}))
164 assert.NoError(compare("bar", []string{"key2"}))
165 assert.NoError(compare("baz", []string{}))
166 }
167
168 func BenchmarkIndexer(b *testing.B) {
169 testIndexer := "testIndexer"
170
171 indexers := Indexers{
172 testIndexer: func(obj interface{}) (strings []string, e error) {
173 indexes := []string{obj.(string)}
174 return indexes, nil
175 },
176 }
177
178 indices := Indices{}
179 store := NewThreadSafeStore(indexers, indices).(*threadSafeMap)
180
181
182
183
184
185 objectCount := 5000
186 objects := make([]string, 0, 5000)
187 for i := 0; i < objectCount; i++ {
188 objects = append(objects, fmt.Sprintf("object-number-%d", i))
189 }
190
191 b.ResetTimer()
192 for i := 0; i < b.N; i++ {
193 store.Update(objects[i%objectCount], objects[i%objectCount])
194 }
195 }
196
View as plain text