jwt_test.TestGetConnectedUserID   F
last analyzed

Complexity

Conditions 14

Size

Total Lines 78
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 49
nop 1
dl 0
loc 78
rs 3.6
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like jwt_test.TestGetConnectedUserID often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package jwt_test
2
3
import (
4
	"bytes"
5
	"context"
6
	"sync"
7
	"testing"
8
9
	"github.com/golang-jwt/jwt/v5"
10
	"github.com/memnix/memnix-rest/pkg/crypto"
11
	myjwt "github.com/memnix/memnix-rest/pkg/jwt"
12
	"github.com/memnix/memnix-rest/pkg/utils"
13
	"github.com/pkg/errors"
14
	"golang.org/x/crypto/ed25519"
15
)
16
17
func TestGetJwtInstance(t *testing.T) {
18
	// Create a wait group to ensure the function is called only once
19
	var wg sync.WaitGroup
20
	wg.Add(2)
21
22
	// Call the function in two goroutines
23
	go func() {
24
		defer wg.Done()
25
		instance1 := myjwt.GetJwtInstance()
26
		if instance1 == nil {
27
			t.Error("GetJwtInstance() returned nil")
28
		}
29
	}()
30
31
	go func() {
32
		defer wg.Done()
33
		instance2 := myjwt.GetJwtInstance()
34
		if instance2 == nil {
35
			t.Error("GetJwtInstance() returned nil")
36
		}
37
	}()
38
39
	// Wait for both goroutines to finish
40
	wg.Wait()
41
}
42
43
func TestNewJWTInstance(t *testing.T) {
44
	headerLen := 10
45
	expirationTime := 24
46
	publicKey := make(ed25519.PublicKey, 32)
47
	privateKey := make(ed25519.PrivateKey, 64)
48
49
	instance := myjwt.NewJWTInstance(headerLen, expirationTime, publicKey, privateKey)
50
51
	if instance.HeaderLen != headerLen {
52
		t.Errorf("Expected HeaderLen to be %d, but got %d", headerLen, instance.HeaderLen)
53
	}
54
55
	if !bytes.Equal(instance.PublicKey, publicKey) {
56
		t.Error("Expected PublicKey to be equal")
57
	}
58
59
	if !bytes.Equal(instance.PrivateKey, privateKey) {
60
		t.Error("Expected PrivateKey to be equal")
61
	}
62
63
	if instance.SigningMethod != jwt.SigningMethodEdDSA {
64
		t.Errorf("Expected signingMethod to be %s, but got %s", jwt.SigningMethodEdDSA, instance.SigningMethod)
65
	}
66
67
	if instance.ExpirationTimeInHours != expirationTime {
68
		t.Errorf("Expected ExpirationTimeInHours to be %d, but got %d", expirationTime, instance.ExpirationTimeInHours)
69
	}
70
}
71
72
func TestSetJwt(t *testing.T) {
73
	// Create a new JWT instance
74
	instance := myjwt.NewJWTInstance(10, 24, make(ed25519.PublicKey, 32), make(ed25519.PrivateKey, 64))
75
76
	// Create a new InstanceSingleton
77
	singleton := &myjwt.InstanceSingleton{}
78
79
	// Set the JWT instance
80
	singleton.SetJwt(instance)
81
82
	// Verify that the JWT instance is set correctly
83
	if !bytes.Equal(singleton.GetJwt().PublicKey, instance.PublicKey) {
84
		t.Error("SetJwt() did not set the JWT instance correctly")
85
	}
86
87
	if !bytes.Equal(singleton.GetJwt().PrivateKey, instance.PrivateKey) {
88
		t.Error("SetJwt() did not set the JWT instance correctly")
89
	}
90
91
	if singleton.GetJwt().HeaderLen != instance.HeaderLen {
92
		t.Error("SetJwt() did not set the JWT instance correctly")
93
	}
94
95
	if singleton.GetJwt().ExpirationTimeInHours != instance.ExpirationTimeInHours {
96
		t.Error("SetJwt() did not set the JWT instance correctly")
97
	}
98
99
	if singleton.GetJwt().SigningMethod != instance.SigningMethod {
100
		t.Error("SetJwt() did not set the JWT instance correctly")
101
	}
102
}
103
104
func TestGetJwt(t *testing.T) {
105
	// Create a new JWT instance
106
	instance := myjwt.NewJWTInstance(10, 24, make(ed25519.PublicKey, 32), make(ed25519.PrivateKey, 64))
107
108
	// Create a new InstanceSingleton
109
	singleton := &myjwt.InstanceSingleton{}
110
111
	// Set the JWT instance
112
	singleton.SetJwt(instance)
113
114
	// Verify that the JWT instance is returned correctly
115
	if !bytes.Equal(singleton.GetJwt().PublicKey, instance.PublicKey) {
116
		t.Error("GetJwt() did not return the JWT instance correctly")
117
	}
118
119
	if !bytes.Equal(singleton.GetJwt().PrivateKey, instance.PrivateKey) {
120
		t.Error("GetJwt() did not return the JWT instance correctly")
121
	}
122
123
	if singleton.GetJwt().HeaderLen != instance.HeaderLen {
124
		t.Error("GetJwt() did not return the JWT instance correctly")
125
	}
126
127
	if singleton.GetJwt().ExpirationTimeInHours != instance.ExpirationTimeInHours {
128
		t.Error("GetJwt() did not return the JWT instance correctly")
129
	}
130
131
	if singleton.GetJwt().SigningMethod != instance.SigningMethod {
132
		t.Error("GetJwt() did not return the JWT instance correctly")
133
	}
134
}
135
136
func ParseEd25519Key() (ed25519.PrivateKey, ed25519.PublicKey, error) {
137
	publicKey, privateKey, err := crypto.GenerateKeyPair()
138
	if err != nil {
139
		return nil, nil, err
140
	}
141
142
	return privateKey, publicKey, nil
143
}
144
145
func TestGenerateToken(t *testing.T) {
146
	privateKey, publicKey, err := ParseEd25519Key()
147
	if err != nil {
148
		t.Fatalf("Unexpected error: %v", err)
149
	}
150
151
	// Create a new JWT instance
152
	instance := myjwt.NewJWTInstance(2, 24, publicKey, privateKey)
153
154
	// Create a mock context
155
	ctx := context.TODO()
156
157
	// Set up test cases
158
	testCases := []struct {
159
		name   string
160
		userID int32
161
	}{
162
		{
163
			name:   "ValidUserID",
164
			userID: 1,
165
		},
166
		{
167
			name:   "InvalidUserID",
168
			userID: 0,
169
		},
170
	}
171
172
	for _, tc := range testCases {
173
		t.Run(tc.name, func(t *testing.T) {
174
			token, err := instance.GenerateToken(ctx, tc.userID)
175
			if err != nil {
176
				t.Fatalf("Unexpected error: %v", err)
177
			}
178
179
			if token == "" {
180
				t.Error("Expected token to be non-empty")
181
			}
182
183
			jwtToken, err := instance.GetToken(ctx, token)
184
			if err != nil {
185
				t.Fatalf("Unexpected error: %v", err)
186
			}
187
188
			// Check if the token is valid.
189
			userID, err := instance.VerifyToken(jwtToken)
190
			if err != nil {
191
				t.Fatalf("Unexpected error: %v", err)
192
			}
193
194
			if userID != tc.userID {
195
				t.Errorf("Expected userID to be %d, but got %d", tc.userID, userID)
196
			}
197
198
			// Get the expiration time from the token
199
			expirationTime := instance.GetExpirationTime(jwtToken)
200
201
			if expirationTime == 0 {
202
				t.Error("Expected expirationTime to be non-zero")
203
			}
204
		})
205
	}
206
}
207
208
func TestExtractToken(t *testing.T) {
209
	privateKey, publicKey, err := ParseEd25519Key()
210
	if err != nil {
211
		t.Fatalf("Unexpected error: %v", err)
212
	}
213
214
	// Create a new JWT instance
215
	instance := myjwt.NewJWTInstance(2, 24, publicKey, privateKey)
216
	token, err := instance.GenerateToken(context.TODO(), 1)
217
	if err != nil {
218
		t.Fatalf("Unexpected error: %v", err)
219
	}
220
221
	testCases := []struct {
222
		name        string
223
		token       string
224
		expected    string
225
		expectedLen int
226
	}{
227
		{
228
			name:     "ValidToken",
229
			token:    "Bearer " + token,
230
			expected: token,
231
		},
232
		{
233
			name:     "InvalidToken",
234
			token:    "Bearer",
235
			expected: "",
236
		},
237
		// Add more test cases here if needed
238
	}
239
240
	for _, tc := range testCases {
241
		t.Run(tc.name, func(t *testing.T) {
242
			result := instance.ExtractToken(tc.token)
243
			if result != tc.expected {
244
				t.Errorf("Expected token to be %s, but got %s", tc.expected, result)
245
			}
246
		})
247
	}
248
}
249
250
func GenerateInvalidToken() string {
251
	// Create a new JWT instance
252
	privateKey, publicKey, err := ParseEd25519Key()
253
	if err != nil {
254
		return ""
255
	}
256
	instance := myjwt.NewJWTInstance(2, 24, publicKey, privateKey)
257
258
	// Create the Claims for the token
259
	claims := jwt.NewWithClaims(instance.SigningMethod, jwt.RegisteredClaims{
260
		Issuer:    utils.ConvertUIntToStr(42),         // Issuer is the user id
261
		ExpiresAt: instance.CalculateExpirationTime(), // ExpiresAt is the expiration time
262
	})
263
264
	// Sign and get the complete encoded token as a string using the secret
265
	token, err := claims.SignedString(instance.PrivateKey)
266
	if err != nil {
267
		return ""
268
	}
269
	return token
270
}
271
272
func GenerateTokenWithString(id string) string {
273
	// Create a new JWT instance
274
	privateKey, publicKey, err := ParseEd25519Key()
275
	if err != nil {
276
		return ""
277
	}
278
	instance := myjwt.NewJWTInstance(2, 24, publicKey, privateKey)
279
280
	// Create the Claims for the token
281
	claims := jwt.NewWithClaims(instance.SigningMethod, jwt.RegisteredClaims{
282
		Issuer:    id,
283
		ExpiresAt: instance.CalculateExpirationTime(), // ExpiresAt is the expiration time
284
	})
285
286
	// Sign and get the complete encoded token as a string using the secret
287
	token, err := claims.SignedString(instance.PrivateKey)
288
	if err != nil {
289
		return ""
290
	}
291
	return token
292
}
293
294
func TestGetConnectedUserID(t *testing.T) {
295
	// Create a mock context
296
	ctx := context.TODO()
297
298
	// Create a new JWT instance
299
	privateKey, publicKey, err := ParseEd25519Key()
300
	if err != nil {
301
		t.Fatalf("Unexpected error: %v", err)
302
	}
303
304
	// Create a new JWT instance
305
	instance := myjwt.NewJWTInstance(2, 24, publicKey, privateKey)
306
307
	token, err := instance.GenerateToken(ctx, 1)
308
	if err != nil {
309
		t.Fatalf("Unexpected error: %v", err)
310
	}
311
312
	zeroToken, err := instance.GenerateToken(ctx, 0)
313
	if err != nil {
314
		t.Fatalf("Unexpected error: %v", err)
315
	}
316
317
	// Set up test cases
318
	testCases := []struct {
319
		expectedErr error
320
		name        string
321
		tokenHeader string
322
		expectedID  int32
323
	}{
324
		{
325
			name:        "ValidToken",
326
			tokenHeader: "Bearer " + token,
327
			expectedID:  1,
328
			expectedErr: nil,
329
		},
330
		{
331
			name:        "InvalidToken",
332
			tokenHeader: "Bearer " + GenerateInvalidToken(),
333
			expectedID:  0,
334
			expectedErr: errors.New("invalid token"),
335
		},
336
		{
337
			name:        "EmptyToken",
338
			tokenHeader: "",
339
			expectedID:  0,
340
			expectedErr: errors.New("empty token"),
341
		},
342
		{
343
			name:        "InvalidTokenHeader",
344
			tokenHeader: "Bearer",
345
			expectedID:  0,
346
			expectedErr: errors.New("empty token"),
347
		},
348
		{
349
			name:        "ZeroToken",
350
			tokenHeader: "Bearer " + zeroToken,
351
			expectedID:  0,
352
			expectedErr: errors.New("invalid token"),
353
		},
354
		{
355
			name:        "StringToken",
356
			tokenHeader: "Bearer " + GenerateTokenWithString("42"),
357
			expectedID:  0,
358
			expectedErr: errors.New("invalid token"),
359
		},
360
	}
361
362
	for _, tc := range testCases {
363
		t.Run(tc.name, func(t *testing.T) {
364
			userID, err := instance.GetConnectedUserID(ctx, tc.tokenHeader)
365
366
			if userID != tc.expectedID {
367
				t.Errorf("Expected userID to be %d, but got %d", tc.expectedID, userID)
368
			}
369
370
			if (err == nil && tc.expectedErr != nil) || (err != nil && tc.expectedErr == nil) || (err != nil && tc.expectedErr != nil && err.Error() != tc.expectedErr.Error()) {
371
				t.Errorf("Expected error to be %v, but got %v", tc.expectedErr, err)
372
			}
373
		})
374
	}
375
}
376
377
func FuzzGenerateToken(f *testing.F) {
378
	privateKey, publicKey, err := ParseEd25519Key()
379
	if err != nil {
380
		f.Fatalf("Unexpected error: %v", err)
381
	}
382
383
	// Create a new JWT instance
384
	instance := myjwt.NewJWTInstance(2, 24, publicKey, privateKey)
385
386
	// Create a mock context
387
	ctx := context.TODO()
388
389
	f.Add(int32(1)) // Add a value to the fuzzing pool
390
391
	f.Fuzz(func(t *testing.T, userID int32) {
392
		token, err := instance.GenerateToken(ctx, userID)
393
		if err != nil {
394
			t.Fatalf("Unexpected error: %v", err)
395
		}
396
397
		if token == "" {
398
			t.Error("Expected token to be non-empty")
399
		}
400
401
		jwtToken, err := instance.GetToken(ctx, token)
402
		if err != nil {
403
			t.Fatalf("Unexpected error: %v", err)
404
		}
405
406
		// Check if the token is valid.
407
		uID, err := instance.VerifyToken(jwtToken)
408
		if err != nil {
409
			t.Fatalf("Unexpected error: %v", err)
410
		}
411
412
		if userID != uID {
413
			t.Errorf("Expected userID to be %d, but got %d", userID, uID)
414
		}
415
	})
416
}
417