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