identity_test.go

  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	// set metadata after commit
209	versionCount := len(identity.versions)
210	identity.SetMetadata("foo", "bar")
211	require.True(t, identity.NeedCommit())
212	require.Len(t, identity.versions, versionCount+1)
213
214	err = identity.Commit(repo)
215	require.NoError(t, err)
216	require.Len(t, identity.versions, versionCount+1)
217}
218
219func assertHasKeyValue(t *testing.T, metadata map[string]string, key, value string) {
220	val, ok := metadata[key]
221	require.True(t, ok)
222	require.Equal(t, val, value)
223}
224
225func TestJSON(t *testing.T) {
226	repo := makeIdentityTestRepo(t)
227
228	identity, err := NewIdentity(repo, "René Descartes", "rene.descartes@example.com")
229	require.NoError(t, err)
230
231	// commit to make sure we have an Id
232	err = identity.Commit(repo)
233	require.NoError(t, err)
234	require.NotEmpty(t, identity.Id())
235
236	// serialize
237	data, err := json.Marshal(identity)
238	require.NoError(t, err)
239
240	// deserialize, got a IdentityStub with the same id
241	var i Interface
242	i, err = UnmarshalJSON(data)
243	require.NoError(t, err)
244	require.Equal(t, identity.Id(), i.Id())
245
246	// make sure we can load the identity properly
247	i, err = ReadLocal(repo, i.Id())
248	require.NoError(t, err)
249}
250
251func TestIdentityRemove(t *testing.T) {
252	repo := repository.CreateGoGitTestRepo(false)
253	remoteA := repository.CreateGoGitTestRepo(true)
254	remoteB := repository.CreateGoGitTestRepo(true)
255	defer repository.CleanupTestRepos(repo, remoteA, remoteB)
256
257	err := repo.AddRemote("remoteA", remoteA.GetLocalRemote())
258	require.NoError(t, err)
259
260	err = repo.AddRemote("remoteB", remoteB.GetLocalRemote())
261	require.NoError(t, err)
262
263	// generate an identity for testing
264	rene, err := NewIdentity(repo, "René Descartes", "rene@descartes.fr")
265	require.NoError(t, err)
266
267	err = rene.Commit(repo)
268	require.NoError(t, err)
269
270	_, err = Push(repo, "remoteA")
271	require.NoError(t, err)
272
273	_, err = Push(repo, "remoteB")
274	require.NoError(t, err)
275
276	_, err = Fetch(repo, "remoteA")
277	require.NoError(t, err)
278
279	_, err = Fetch(repo, "remoteB")
280	require.NoError(t, err)
281
282	err = RemoveIdentity(repo, rene.Id())
283	require.NoError(t, err)
284
285	_, err = ReadLocal(repo, rene.Id())
286	require.Error(t, ErrIdentityNotExist, err)
287
288	_, err = ReadRemote(repo, "remoteA", string(rene.Id()))
289	require.Error(t, ErrIdentityNotExist, err)
290
291	_, err = ReadRemote(repo, "remoteB", string(rene.Id()))
292	require.Error(t, ErrIdentityNotExist, err)
293
294	ids, err := ListLocalIds(repo)
295	require.NoError(t, err)
296	require.Len(t, ids, 0)
297}