identity_test.go

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