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 require.NoError(t, cache.load())
87 require.Empty(t, cache.bugs)
88 require.Empty(t, cache.identities)
89 require.Len(t, cache.bugExcerpts, 2)
90 require.Len(t, cache.identitiesExcerpts, 2)
91
92 // Resolving load from the disk
93 _, err = cache.ResolveIdentity(iden1.Id())
94 require.NoError(t, err)
95 _, err = cache.ResolveIdentityExcerpt(iden1.Id())
96 require.NoError(t, err)
97 _, err = cache.ResolveIdentityPrefix(iden1.Id().String()[:10])
98 require.NoError(t, err)
99
100 _, err = cache.ResolveBug(bug1.Id())
101 require.NoError(t, err)
102 _, err = cache.ResolveBugExcerpt(bug1.Id())
103 require.NoError(t, err)
104 _, err = cache.ResolveBugPrefix(bug1.Id().String()[:10])
105 require.NoError(t, err)
106}
107
108func TestPushPull(t *testing.T) {
109 repoA, repoB, remote := repository.SetupReposAndRemote()
110 defer repository.CleanupTestRepos(repoA, repoB, remote)
111
112 cacheA, err := NewRepoCache(repoA)
113 require.NoError(t, err)
114
115 cacheB, err := NewRepoCache(repoB)
116 require.NoError(t, err)
117
118 // Create, set and get user identity
119 reneA, err := cacheA.NewIdentity("René Descartes", "rene@descartes.fr")
120 require.NoError(t, err)
121 err = cacheA.SetUserIdentity(reneA)
122 require.NoError(t, err)
123
124 // distribute the identity
125 _, err = cacheA.Push("origin")
126 require.NoError(t, err)
127 err = cacheB.Pull("origin")
128 require.NoError(t, err)
129
130 // Create a bug in A
131 _, _, err = cacheA.NewBug("bug1", "message")
132 require.NoError(t, err)
133
134 // A --> remote --> B
135 _, err = cacheA.Push("origin")
136 require.NoError(t, err)
137
138 err = cacheB.Pull("origin")
139 require.NoError(t, err)
140
141 require.Len(t, cacheB.AllBugsIds(), 1)
142
143 // retrieve and set identity
144 reneB, err := cacheB.ResolveIdentity(reneA.Id())
145 require.NoError(t, err)
146
147 err = cacheB.SetUserIdentity(reneB)
148 require.NoError(t, err)
149
150 // B --> remote --> A
151 _, _, err = cacheB.NewBug("bug2", "message")
152 require.NoError(t, err)
153
154 _, err = cacheB.Push("origin")
155 require.NoError(t, err)
156
157 err = cacheA.Pull("origin")
158 require.NoError(t, err)
159
160 require.Len(t, cacheA.AllBugsIds(), 2)
161}
162
163func TestRemove(t *testing.T) {
164 repo := repository.CreateTestRepo(false)
165 remoteA := repository.CreateTestRepo(true)
166 remoteB := repository.CreateTestRepo(true)
167 defer repository.CleanupTestRepos(repo, remoteA, remoteB)
168
169 err := repo.AddRemote("remoteA", "file://"+remoteA.GetPath())
170 require.NoError(t, err)
171
172 err = repo.AddRemote("remoteB", "file://"+remoteB.GetPath())
173 require.NoError(t, err)
174
175 repoCache, err := NewRepoCache(repo)
176 require.NoError(t, err)
177
178 // generate a bunch of bugs
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 for i := 0; i < 100; i++ {
186 _, _, err := repoCache.NewBug("title", "message")
187 require.NoError(t, err)
188 }
189
190 // and one more for testing
191 b1, _, err := repoCache.NewBug("title", "message")
192 require.NoError(t, err)
193
194 _, err = repoCache.Push("remoteA")
195 require.NoError(t, err)
196
197 _, err = repoCache.Push("remoteB")
198 require.NoError(t, err)
199
200 _, err = repoCache.Fetch("remoteA")
201 require.NoError(t, err)
202
203 _, err = repoCache.Fetch("remoteB")
204 require.NoError(t, err)
205
206 err = repoCache.RemoveBug(b1.Id().String())
207 require.NoError(t, err)
208 assert.Equal(t, 100, len(repoCache.bugs))
209 assert.Equal(t, 100, len(repoCache.bugExcerpts))
210
211 _, err = repoCache.ResolveBug(b1.Id())
212 assert.Error(t, bug.ErrBugNotExist, err)
213}
214
215func TestCacheEviction(t *testing.T) {
216 repo := repository.CreateTestRepo(false)
217 repoCache, err := NewRepoCache(repo)
218 require.NoError(t, err)
219 repoCache.presentBugs.Resize(2)
220
221 require.Equal(t, 0, repoCache.presentBugs.Len())
222 require.Equal(t, 0, len(repoCache.bugs))
223 require.Equal(t, 0, len(repoCache.bugExcerpts))
224
225 // Generating some bugs
226 rene, err := repoCache.NewIdentity("René Descartes", "rene@descartes.fr")
227 require.NoError(t, err)
228 err = repoCache.SetUserIdentity(rene)
229 require.NoError(t, err)
230
231 bug1, _, err := repoCache.NewBug("title", "message")
232 require.NoError(t, err)
233
234 checkBugPresence(t, repoCache, bug1, true)
235 require.Equal(t, 1, repoCache.presentBugs.Len())
236 require.Equal(t, 1, len(repoCache.bugs))
237 require.Equal(t, 1, len(repoCache.bugExcerpts))
238
239 bug2, _, err := repoCache.NewBug("title", "message")
240 require.NoError(t, err)
241
242 checkBugPresence(t, repoCache, bug1, true)
243 checkBugPresence(t, repoCache, bug2, true)
244 require.Equal(t, 2, repoCache.presentBugs.Len())
245 require.Equal(t, 2, len(repoCache.bugs))
246 require.Equal(t, 2, len(repoCache.bugExcerpts))
247
248 // Number of bugs should not exceed max size of lruCache, oldest one should be evicted
249 bug3, _, err := repoCache.NewBug("title", "message")
250 require.NoError(t, err)
251
252 checkBugPresence(t, repoCache, bug1, false)
253 checkBugPresence(t, repoCache, bug2, true)
254 checkBugPresence(t, repoCache, bug3, true)
255 require.Equal(t, 2, repoCache.presentBugs.Len())
256 require.Equal(t, 2, len(repoCache.bugs))
257 require.Equal(t, 2, len(repoCache.bugExcerpts))
258
259 // Accessing bug should update position in lruCache and therefore it should not be evicted
260 repoCache.presentBugs.Get(bug2.Id())
261 oldestId, _ := repoCache.presentBugs.GetOldest()
262 require.Equal(t, bug3.Id(), oldestId)
263
264 checkBugPresence(t, repoCache, bug1, false)
265 checkBugPresence(t, repoCache, bug2, true)
266 checkBugPresence(t, repoCache, bug3, true)
267 require.Equal(t, 2, repoCache.presentBugs.Len())
268 require.Equal(t, 2, len(repoCache.bugs))
269 require.Equal(t, 2, len(repoCache.bugExcerpts))
270}
271
272func checkBugPresence(t *testing.T, cache *RepoCache, bug *BugCache, presence bool) {
273 id := bug.Id()
274 require.Equal(t, presence, cache.presentBugs.Contains(id))
275 b, ok := cache.bugs[id]
276 require.Equal(t, presence, ok)
277 require.Equal(t, bug, b)
278 _, ok = cache.bugExcerpts[id]
279 require.Equal(t, presence, ok)
280}