1package identity
2
3import (
4 "encoding/json"
5 "testing"
6
7 "github.com/stretchr/testify/require"
8
9 "github.com/MichaelMure/git-bug/repository"
10 "github.com/MichaelMure/git-bug/util/lamport"
11)
12
13// Test the commit and load of an Identity with multiple versions
14func TestIdentityCommitLoad(t *testing.T) {
15 repo := makeIdentityTestRepo(t)
16
17 // single version
18
19 identity, err := NewIdentity(repo, "René Descartes", "rene.descartes@example.com")
20 require.NoError(t, err)
21
22 idBeforeCommit := identity.Id()
23
24 err = identity.Commit(repo)
25 require.NoError(t, err)
26
27 commitsAreSet(t, identity)
28 require.NotEmpty(t, identity.Id())
29 require.Equal(t, idBeforeCommit, identity.Id())
30 require.Equal(t, idBeforeCommit, identity.versions[0].Id())
31
32 loaded, err := ReadLocal(repo, identity.Id())
33 require.NoError(t, err)
34 commitsAreSet(t, loaded)
35 require.Equal(t, identity, loaded)
36
37 // multiple versions
38
39 identity, err = NewIdentityFull(repo, "René Descartes", "rene.descartes@example.com", "", "", []*Key{{PubKey: "pubkeyA"}})
40 require.NoError(t, err)
41
42 idBeforeCommit = identity.Id()
43
44 err = identity.Mutate(repo, func(orig *Mutator) {
45 orig.Keys = []*Key{{PubKey: "pubkeyB"}}
46 })
47 require.NoError(t, err)
48
49 err = identity.Mutate(repo, func(orig *Mutator) {
50 orig.Keys = []*Key{{PubKey: "pubkeyC"}}
51 })
52 require.NoError(t, err)
53
54 require.Equal(t, idBeforeCommit, identity.Id())
55
56 err = identity.Commit(repo)
57 require.NoError(t, err)
58
59 commitsAreSet(t, identity)
60 require.NotEmpty(t, identity.Id())
61 require.Equal(t, idBeforeCommit, identity.Id())
62 require.Equal(t, idBeforeCommit, identity.versions[0].Id())
63
64 loaded, err = ReadLocal(repo, identity.Id())
65 require.NoError(t, err)
66 commitsAreSet(t, loaded)
67 require.Equal(t, identity, loaded)
68
69 // add more version
70
71 err = identity.Mutate(repo, func(orig *Mutator) {
72 orig.Email = "rene@descartes.com"
73 orig.Keys = []*Key{{PubKey: "pubkeyD"}}
74 })
75 require.NoError(t, err)
76
77 err = identity.Mutate(repo, func(orig *Mutator) {
78 orig.Email = "rene@descartes.com"
79 orig.Keys = []*Key{{PubKey: "pubkeyD"}, {PubKey: "pubkeyE"}}
80 })
81 require.NoError(t, err)
82
83 err = identity.Commit(repo)
84 require.NoError(t, err)
85
86 commitsAreSet(t, identity)
87 require.NotEmpty(t, identity.Id())
88 require.Equal(t, idBeforeCommit, identity.Id())
89 require.Equal(t, idBeforeCommit, identity.versions[0].Id())
90
91 loaded, err = ReadLocal(repo, identity.Id())
92 require.NoError(t, err)
93 commitsAreSet(t, loaded)
94 require.Equal(t, identity, loaded)
95}
96
97func TestIdentityMutate(t *testing.T) {
98 repo := makeIdentityTestRepo(t)
99
100 identity, err := NewIdentity(repo, "René Descartes", "rene.descartes@example.com")
101 require.NoError(t, err)
102
103 require.Len(t, identity.versions, 1)
104
105 err = identity.Mutate(repo, func(orig *Mutator) {
106 orig.Email = "rene@descartes.fr"
107 orig.Name = "René"
108 orig.Login = "rene"
109 })
110 require.NoError(t, err)
111
112 require.Len(t, identity.versions, 2)
113 require.Equal(t, identity.Email(), "rene@descartes.fr")
114 require.Equal(t, identity.Name(), "René")
115 require.Equal(t, identity.Login(), "rene")
116}
117
118func commitsAreSet(t *testing.T, identity *Identity) {
119 for _, version := range identity.versions {
120 require.NotEmpty(t, version.commitHash)
121 }
122}
123
124// Test that the correct crypto keys are returned for a given lamport time
125func TestIdentity_ValidKeysAtTime(t *testing.T) {
126 identity := Identity{
127 versions: []*version{
128 {
129 times: map[string]lamport.Time{"foo": 100},
130 keys: []*Key{
131 {PubKey: "pubkeyA"},
132 },
133 },
134 {
135 times: map[string]lamport.Time{"foo": 200},
136 keys: []*Key{
137 {PubKey: "pubkeyB"},
138 },
139 },
140 {
141 times: map[string]lamport.Time{"foo": 201},
142 keys: []*Key{
143 {PubKey: "pubkeyC"},
144 },
145 },
146 {
147 times: map[string]lamport.Time{"foo": 201},
148 keys: []*Key{
149 {PubKey: "pubkeyD"},
150 },
151 },
152 {
153 times: map[string]lamport.Time{"foo": 300},
154 keys: []*Key{
155 {PubKey: "pubkeyE"},
156 },
157 },
158 },
159 }
160
161 require.Nil(t, identity.ValidKeysAtTime("foo", 10))
162 require.Equal(t, identity.ValidKeysAtTime("foo", 100), []*Key{{PubKey: "pubkeyA"}})
163 require.Equal(t, identity.ValidKeysAtTime("foo", 140), []*Key{{PubKey: "pubkeyA"}})
164 require.Equal(t, identity.ValidKeysAtTime("foo", 200), []*Key{{PubKey: "pubkeyB"}})
165 require.Equal(t, identity.ValidKeysAtTime("foo", 201), []*Key{{PubKey: "pubkeyD"}})
166 require.Equal(t, identity.ValidKeysAtTime("foo", 202), []*Key{{PubKey: "pubkeyD"}})
167 require.Equal(t, identity.ValidKeysAtTime("foo", 300), []*Key{{PubKey: "pubkeyE"}})
168 require.Equal(t, identity.ValidKeysAtTime("foo", 3000), []*Key{{PubKey: "pubkeyE"}})
169}
170
171// Test the immutable or mutable metadata search
172func TestMetadata(t *testing.T) {
173 repo := makeIdentityTestRepo(t)
174
175 identity, err := NewIdentity(repo, "René Descartes", "rene.descartes@example.com")
176 require.NoError(t, err)
177
178 identity.SetMetadata("key1", "value1")
179 assertHasKeyValue(t, identity.ImmutableMetadata(), "key1", "value1")
180 assertHasKeyValue(t, identity.MutableMetadata(), "key1", "value1")
181
182 err = identity.Commit(repo)
183 require.NoError(t, err)
184
185 assertHasKeyValue(t, identity.ImmutableMetadata(), "key1", "value1")
186 assertHasKeyValue(t, identity.MutableMetadata(), "key1", "value1")
187
188 // try override
189 err = identity.Mutate(repo, func(orig *Mutator) {
190 orig.Email = "rene@descartes.fr"
191 })
192 require.NoError(t, err)
193
194 identity.SetMetadata("key1", "value2")
195 assertHasKeyValue(t, identity.ImmutableMetadata(), "key1", "value1")
196 assertHasKeyValue(t, identity.MutableMetadata(), "key1", "value2")
197
198 err = identity.Commit(repo)
199 require.NoError(t, err)
200
201 // reload
202 loaded, err := ReadLocal(repo, identity.Id())
203 require.NoError(t, err)
204
205 assertHasKeyValue(t, loaded.ImmutableMetadata(), "key1", "value1")
206 assertHasKeyValue(t, loaded.MutableMetadata(), "key1", "value2")
207}
208
209func assertHasKeyValue(t *testing.T, metadata map[string]string, key, value string) {
210 val, ok := metadata[key]
211 require.True(t, ok)
212 require.Equal(t, val, value)
213}
214
215func TestJSON(t *testing.T) {
216 repo := makeIdentityTestRepo(t)
217
218 identity, err := NewIdentity(repo, "René Descartes", "rene.descartes@example.com")
219 require.NoError(t, err)
220
221 // commit to make sure we have an Id
222 err = identity.Commit(repo)
223 require.NoError(t, err)
224 require.NotEmpty(t, identity.Id())
225
226 // serialize
227 data, err := json.Marshal(identity)
228 require.NoError(t, err)
229
230 // deserialize, got a IdentityStub with the same id
231 var i Interface
232 i, err = UnmarshalJSON(data)
233 require.NoError(t, err)
234 require.Equal(t, identity.Id(), i.Id())
235
236 // make sure we can load the identity properly
237 i, err = ReadLocal(repo, i.Id())
238 require.NoError(t, err)
239}
240
241func TestIdentityRemove(t *testing.T) {
242 repo := repository.CreateGoGitTestRepo(false)
243 remoteA := repository.CreateGoGitTestRepo(true)
244 remoteB := repository.CreateGoGitTestRepo(true)
245 defer repository.CleanupTestRepos(repo, remoteA, remoteB)
246
247 err := repo.AddRemote("remoteA", remoteA.GetLocalRemote())
248 require.NoError(t, err)
249
250 err = repo.AddRemote("remoteB", remoteB.GetLocalRemote())
251 require.NoError(t, err)
252
253 // generate an identity for testing
254 rene, err := NewIdentity(repo, "René Descartes", "rene@descartes.fr")
255 require.NoError(t, err)
256
257 err = rene.Commit(repo)
258 require.NoError(t, err)
259
260 _, err = Push(repo, "remoteA")
261 require.NoError(t, err)
262
263 _, err = Push(repo, "remoteB")
264 require.NoError(t, err)
265
266 _, err = Fetch(repo, "remoteA")
267 require.NoError(t, err)
268
269 _, err = Fetch(repo, "remoteB")
270 require.NoError(t, err)
271
272 err = RemoveIdentity(repo, rene.Id())
273 require.NoError(t, err)
274
275 _, err = ReadLocal(repo, rene.Id())
276 require.Error(t, ErrIdentityNotExist, err)
277
278 _, err = ReadRemote(repo, "remoteA", string(rene.Id()))
279 require.Error(t, ErrIdentityNotExist, err)
280
281 _, err = ReadRemote(repo, "remoteB", string(rene.Id()))
282 require.Error(t, ErrIdentityNotExist, err)
283
284 ids, err := ListLocalIds(repo)
285 require.NoError(t, err)
286 require.Len(t, ids, 0)
287}