1package cache
2
3import (
4 "testing"
5
6 "github.com/stretchr/testify/assert"
7 "github.com/stretchr/testify/require"
8
9 "github.com/MichaelMure/git-bug/bug"
10 "github.com/MichaelMure/git-bug/query"
11 "github.com/MichaelMure/git-bug/repository"
12)
13
14func TestCache(t *testing.T) {
15 repo := repository.CreateTestRepo(false)
16 defer repository.CleanupTestRepos(repo)
17
18 cache, err := NewRepoCache(repo)
19 require.NoError(t, err)
20
21 // Create, set and get user identity
22 iden1, err := cache.NewIdentity("René Descartes", "rene@descartes.fr")
23 require.NoError(t, err)
24 err = cache.SetUserIdentity(iden1)
25 require.NoError(t, err)
26 userIden, err := cache.GetUserIdentity()
27 require.NoError(t, err)
28 require.Equal(t, iden1.Id(), userIden.Id())
29
30 // it's possible to create two identical identities
31 iden2, err := cache.NewIdentity("René Descartes", "rene@descartes.fr")
32 require.NoError(t, err)
33
34 // Two identical identities yield a different id
35 require.NotEqual(t, iden1.Id(), iden2.Id())
36
37 // There is now two identities in the cache
38 require.Len(t, cache.AllIdentityIds(), 2)
39 require.Len(t, cache.identitiesExcerpts, 2)
40 require.Len(t, cache.identities, 2)
41
42 // Create a bug
43 bug1, _, err := cache.NewBug("title", "message")
44 require.NoError(t, err)
45
46 // It's possible to create two identical bugs
47 bug2, _, err := cache.NewBug("title", "message")
48 require.NoError(t, err)
49
50 // two identical bugs yield a different id
51 require.NotEqual(t, bug1.Id(), bug2.Id())
52
53 // There is now two bugs in the cache
54 require.Len(t, cache.AllBugsIds(), 2)
55 require.Len(t, cache.bugExcerpts, 2)
56 require.Len(t, cache.bugs, 2)
57
58 // Resolving
59 _, err = cache.ResolveIdentity(iden1.Id())
60 require.NoError(t, err)
61 _, err = cache.ResolveIdentityExcerpt(iden1.Id())
62 require.NoError(t, err)
63 _, err = cache.ResolveIdentityPrefix(iden1.Id().String()[:10])
64 require.NoError(t, err)
65
66 _, err = cache.ResolveBug(bug1.Id())
67 require.NoError(t, err)
68 _, err = cache.ResolveBugExcerpt(bug1.Id())
69 require.NoError(t, err)
70 _, err = cache.ResolveBugPrefix(bug1.Id().String()[:10])
71 require.NoError(t, err)
72
73 // Querying
74 q, err := query.Parse("status:open author:descartes sort:edit-asc")
75 require.NoError(t, err)
76 require.Len(t, cache.QueryBugs(q), 2)
77
78 // Close
79 require.NoError(t, cache.Close())
80 require.Empty(t, cache.bugs)
81 require.Empty(t, cache.bugExcerpts)
82 require.Empty(t, cache.identities)
83 require.Empty(t, cache.identitiesExcerpts)
84
85 // Reload, only excerpt are loaded
86 cache, err = NewRepoCache(repo)
87 require.NoError(t, err)
88 require.Empty(t, cache.bugs)
89 require.Empty(t, cache.identities)
90 require.Len(t, cache.bugExcerpts, 2)
91 require.Len(t, cache.identitiesExcerpts, 2)
92
93 // Resolving load from the disk
94 _, err = cache.ResolveIdentity(iden1.Id())
95 require.NoError(t, err)
96 _, err = cache.ResolveIdentityExcerpt(iden1.Id())
97 require.NoError(t, err)
98 _, err = cache.ResolveIdentityPrefix(iden1.Id().String()[:10])
99 require.NoError(t, err)
100
101 _, err = cache.ResolveBug(bug1.Id())
102 require.NoError(t, err)
103 _, err = cache.ResolveBugExcerpt(bug1.Id())
104 require.NoError(t, err)
105 _, err = cache.ResolveBugPrefix(bug1.Id().String()[:10])
106 require.NoError(t, err)
107}
108
109func TestPushPull(t *testing.T) {
110 repoA, repoB, remote := repository.SetupReposAndRemote()
111 defer repository.CleanupTestRepos(repoA, repoB, remote)
112
113 cacheA, err := NewRepoCache(repoA)
114 require.NoError(t, err)
115
116 cacheB, err := NewRepoCache(repoB)
117 require.NoError(t, err)
118
119 // Create, set and get user identity
120 reneA, err := cacheA.NewIdentity("René Descartes", "rene@descartes.fr")
121 require.NoError(t, err)
122 err = cacheA.SetUserIdentity(reneA)
123 require.NoError(t, err)
124
125 // distribute the identity
126 _, err = cacheA.Push("origin")
127 require.NoError(t, err)
128 err = cacheB.Pull("origin")
129 require.NoError(t, err)
130
131 // Create a bug in A
132 _, _, err = cacheA.NewBug("bug1", "message")
133 require.NoError(t, err)
134
135 // A --> remote --> B
136 _, err = cacheA.Push("origin")
137 require.NoError(t, err)
138
139 err = cacheB.Pull("origin")
140 require.NoError(t, err)
141
142 require.Len(t, cacheB.AllBugsIds(), 1)
143
144 // retrieve and set identity
145 reneB, err := cacheB.ResolveIdentity(reneA.Id())
146 require.NoError(t, err)
147
148 err = cacheB.SetUserIdentity(reneB)
149 require.NoError(t, err)
150
151 // B --> remote --> A
152 _, _, err = cacheB.NewBug("bug2", "message")
153 require.NoError(t, err)
154
155 _, err = cacheB.Push("origin")
156 require.NoError(t, err)
157
158 err = cacheA.Pull("origin")
159 require.NoError(t, err)
160
161 require.Len(t, cacheA.AllBugsIds(), 2)
162}
163
164func TestRemove(t *testing.T) {
165 repo := repository.CreateTestRepo(false)
166 remoteA := repository.CreateTestRepo(true)
167 remoteB := repository.CreateTestRepo(true)
168 defer repository.CleanupTestRepos(repo, remoteA, remoteB)
169
170 err := repo.AddRemote("remoteA", "file://"+remoteA.GetPath())
171 require.NoError(t, err)
172
173 err = repo.AddRemote("remoteB", "file://"+remoteB.GetPath())
174 require.NoError(t, err)
175
176 repoCache, err := NewRepoCache(repo)
177 require.NoError(t, err)
178
179 rene, err := repoCache.NewIdentity("René Descartes", "rene@descartes.fr")
180 require.NoError(t, err)
181
182 err = repoCache.SetUserIdentity(rene)
183 require.NoError(t, err)
184
185 _, _, err = repoCache.NewBug("title", "message")
186 require.NoError(t, err)
187
188 // and one more for testing
189 b1, _, err := repoCache.NewBug("title", "message")
190 require.NoError(t, err)
191
192 _, err = repoCache.Push("remoteA")
193 require.NoError(t, err)
194
195 _, err = repoCache.Push("remoteB")
196 require.NoError(t, err)
197
198 _, err = repoCache.Fetch("remoteA")
199 require.NoError(t, err)
200
201 _, err = repoCache.Fetch("remoteB")
202 require.NoError(t, err)
203
204 err = repoCache.RemoveBug(b1.Id().String())
205 require.NoError(t, err)
206 assert.Equal(t, 1, len(repoCache.bugs))
207 assert.Equal(t, 1, len(repoCache.bugExcerpts))
208
209 _, err = repoCache.ResolveBug(b1.Id())
210 assert.Error(t, bug.ErrBugNotExist, err)
211}
212
213func TestCacheEviction(t *testing.T) {
214 repo := repository.CreateTestRepo(false)
215 repoCache, err := NewRepoCache(repo)
216 require.NoError(t, err)
217 repoCache.setCacheSize(2)
218
219 require.Equal(t, 2, repoCache.maxLoadedBugs)
220 require.Equal(t, 0, repoCache.loadedBugs.Len())
221 require.Equal(t, 0, len(repoCache.bugs))
222
223 // Generating some bugs
224 rene, err := repoCache.NewIdentity("René Descartes", "rene@descartes.fr")
225 require.NoError(t, err)
226 err = repoCache.SetUserIdentity(rene)
227 require.NoError(t, err)
228
229 bug1, _, err := repoCache.NewBug("title", "message")
230 require.NoError(t, err)
231
232 checkBugPresence(t, repoCache, bug1, true)
233 require.Equal(t, 1, repoCache.loadedBugs.Len())
234 require.Equal(t, 1, len(repoCache.bugs))
235
236 bug2, _, err := repoCache.NewBug("title", "message")
237 require.NoError(t, err)
238
239 checkBugPresence(t, repoCache, bug1, true)
240 checkBugPresence(t, repoCache, bug2, true)
241 require.Equal(t, 2, repoCache.loadedBugs.Len())
242 require.Equal(t, 2, len(repoCache.bugs))
243
244 // Number of bugs should not exceed max size of lruCache, oldest one should be evicted
245 bug3, _, err := repoCache.NewBug("title", "message")
246 require.NoError(t, err)
247
248 require.Equal(t, 2, repoCache.loadedBugs.Len())
249 require.Equal(t, 2, len(repoCache.bugs))
250 checkBugPresence(t, repoCache, bug1, false)
251 checkBugPresence(t, repoCache, bug2, true)
252 checkBugPresence(t, repoCache, bug3, true)
253
254 // Accessing bug should update position in lruCache and therefore it should not be evicted
255 repoCache.loadedBugs.Get(bug2.Id())
256 oldestId, _ := repoCache.loadedBugs.GetOldest()
257 require.Equal(t, bug3.Id(), oldestId)
258
259 checkBugPresence(t, repoCache, bug1, false)
260 checkBugPresence(t, repoCache, bug2, true)
261 checkBugPresence(t, repoCache, bug3, true)
262 require.Equal(t, 2, repoCache.loadedBugs.Len())
263 require.Equal(t, 2, len(repoCache.bugs))
264}
265
266func checkBugPresence(t *testing.T, cache *RepoCache, bug *BugCache, presence bool) {
267 id := bug.Id()
268 require.Equal(t, presence, cache.loadedBugs.Contains(id))
269 b, ok := cache.bugs[id]
270 require.Equal(t, presence, ok)
271 if ok {
272 require.Equal(t, bug, b)
273 }
274}