@@ -195,7 +195,16 @@ func TestTokenExpiredWrite(t *testing.T) {
195
195
require .Nil (t , token )
196
196
})
197
197
}
198
+
199
+ var testMutex sync.Mutex
200
+
198
201
func resetGlobalState () {
202
+ testMutex .Lock ()
203
+ defer testMutex .Unlock ()
204
+
205
+ // Wait longer to ensure all callback goroutines complete
206
+ time .Sleep (500 * time .Millisecond )
207
+
199
208
tokenLoadOnce = sync.Once {}
200
209
tokenCacheOnce = sync.Once {}
201
210
tokenSaveOnce = sync.Once {}
@@ -208,7 +217,6 @@ func resetGlobalState() {
208
217
os .RemoveAll (cacheDir )
209
218
}
210
219
}
211
-
212
220
func setupTestHomeDir (t * testing.T ) (cleanup func ()) {
213
221
tempDir := t .TempDir ()
214
222
originalHome := os .Getenv ("HOME" )
@@ -310,12 +318,8 @@ func createSecurityProvider(mockClient *mockExternalLoginClient, initialToken *a
310
318
)
311
319
}
312
320
313
- var testMutex sync.Mutex
314
-
315
321
func TestLoginOnlyOnce (t * testing.T ) {
316
322
t .Run ("login called only once across multiple requests" , func (t * testing.T ) {
317
- testMutex .Lock ()
318
- defer testMutex .Unlock ()
319
323
resetGlobalState ()
320
324
cleanup := setupTestHomeDir (t )
321
325
defer cleanup ()
@@ -329,26 +333,18 @@ func TestLoginOnlyOnce(t *testing.T) {
329
333
provider := createSecurityProvider (mockClient , nil , & callbackCount )
330
334
require .Nil (t , provider .AuthenticationToken )
331
335
332
- // Add debug logging
333
- t .Logf ("Before Intercept - Token: %v" , provider .AuthenticationToken )
334
- t .Logf ("Before Intercept - Login count: %d" , mockClient .getLoginCount ())
335
-
336
336
req1 := httptest .NewRequest ("GET" , "http://example.com/api/v1/repositories" , nil )
337
337
err := provider .Intercept (context .Background (), req1 )
338
338
339
- t .Logf ("After Intercept - Token: %v" , provider .AuthenticationToken )
340
- t .Logf ("After Intercept - Login count: %d" , mockClient .getLoginCount ())
341
- t .Logf ("Authorization header: %s" , req1 .Header .Get ("Authorization" ))
342
-
343
339
require .NoError (t , err )
344
340
require .Equal (t , "Bearer cached-token" , req1 .Header .Get ("Authorization" ))
345
341
require .Equal (t , int64 (1 ), mockClient .getLoginCount ())
342
+
343
+ // Wait for callback goroutine to complete
344
+ time .Sleep (200 * time .Millisecond )
346
345
})
347
- // }
348
- // func TestNoLoginWhenTokenIsGiven(t *testing.T) {
346
+
349
347
t .Run ("no login performed when valid token provided initially" , func (t * testing.T ) {
350
- testMutex .Lock ()
351
- defer testMutex .Unlock ()
352
348
resetGlobalState ()
353
349
cleanup := setupTestHomeDir (t )
354
350
defer cleanup ()
@@ -367,20 +363,17 @@ func TestLoginOnlyOnce(t *testing.T) {
367
363
var callbackCount int64
368
364
provider := createSecurityProvider (mockClient , existingToken , & callbackCount )
369
365
370
- // Request should use existing token, no login
371
366
req := httptest .NewRequest ("GET" , "http://example.com/api/v1/repositories" , nil )
372
367
err := provider .Intercept (context .Background (), req )
373
368
require .NoError (t , err )
374
369
require .Equal (t , "Bearer pre-existing-token" , req .Header .Get ("Authorization" ))
375
- require .Equal (t , int64 (0 ), mockClient .getLoginCount ()) // No login called
376
- time .Sleep (time .Second )
377
- require .Equal (t , int64 (0 ), atomic .LoadInt64 (& callbackCount )) // No callback called
370
+ require .Equal (t , int64 (0 ), mockClient .getLoginCount ())
371
+
372
+ time .Sleep (200 * time .Millisecond )
373
+ require .Equal (t , int64 (0 ), atomic .LoadInt64 (& callbackCount ))
378
374
})
379
- // }
380
- // func TestRealInterceptWithGlobalCache2(t *testing.T) {
375
+
381
376
t .Run ("handles login failure gracefully" , func (t * testing.T ) {
382
- testMutex .Lock ()
383
- defer testMutex .Unlock ()
384
377
resetGlobalState ()
385
378
cleanup := setupTestHomeDir (t )
386
379
defer cleanup ()
@@ -393,20 +386,17 @@ func TestLoginOnlyOnce(t *testing.T) {
393
386
var callbackCount int64
394
387
provider := createSecurityProvider (mockClient , nil , & callbackCount )
395
388
396
- // Request should fail due to login failure
397
389
req := httptest .NewRequest ("GET" , "http://example.com/api/v1/repositories" , nil )
398
390
err := provider .Intercept (context .Background (), req )
399
391
require .ErrorIs (t , err , errMockLoginFailed )
400
392
require .Empty (t , req .Header .Get ("Authorization" ))
401
- require .Equal (t , int64 (1 ), mockClient .getLoginCount ()) // Login attempted once
402
- time .Sleep (time .Second )
403
- require .Equal (t , int64 (0 ), atomic .LoadInt64 (& callbackCount )) // No callback on failure
393
+ require .Equal (t , int64 (1 ), mockClient .getLoginCount ())
394
+
395
+ time .Sleep (200 * time .Millisecond )
396
+ require .Equal (t , int64 (0 ), atomic .LoadInt64 (& callbackCount ))
404
397
})
405
- // }
406
- // func TestRealInterceptWithGlobalCache5(t *testing.T) {
398
+
407
399
t .Run ("token cached via callback and reused after provider recreation" , func (t * testing.T ) {
408
- testMutex .Lock ()
409
- defer testMutex .Unlock ()
410
400
resetGlobalState ()
411
401
cleanup := setupTestHomeDir (t )
412
402
defer cleanup ()
@@ -419,34 +409,31 @@ func TestLoginOnlyOnce(t *testing.T) {
419
409
var callbackCount int64
420
410
provider1 := createSecurityProvider (mockClient , nil , & callbackCount )
421
411
422
- // First request - should trigger login and cache via callback
423
412
req1 := httptest .NewRequest ("GET" , "http://example.com/api/v1/repositories" , nil )
424
413
err := provider1 .Intercept (context .Background (), req1 )
425
414
require .NoError (t , err )
426
415
require .Equal (t , "Bearer callback-cached-token" , req1 .Header .Get ("Authorization" ))
427
416
require .Equal (t , int64 (1 ), mockClient .getLoginCount ())
428
- time .Sleep (time .Second )
417
+
418
+ time .Sleep (200 * time .Millisecond )
429
419
require .Equal (t , int64 (1 ), atomic .LoadInt64 (& callbackCount ))
430
420
431
- // Verify token was saved to global cache
432
421
require .NotNil (t , cachedToken )
433
422
require .Equal (t , "callback-cached-token" , cachedToken .Token )
434
423
435
- // Create new provider instance (simulating new command execution)
436
424
mockClient .resetLoginCount ()
437
425
callbackCount = 0
438
426
439
- // Get token from cache using global function
440
427
cachedTokenFromFile := getTokenOnce ()
441
428
provider2 := createSecurityProvider (mockClient , cachedTokenFromFile , & callbackCount )
442
429
443
- // Second request with new provider should use cached token from file
444
430
req2 := httptest .NewRequest ("GET" , "http://example.com/api/v1/repositories" , nil )
445
431
err = provider2 .Intercept (context .Background (), req2 )
446
432
require .NoError (t , err )
447
433
require .Equal (t , "Bearer callback-cached-token" , req2 .Header .Get ("Authorization" ))
448
- require .Equal (t , int64 (0 ), mockClient .getLoginCount ()) // No new login, used cache
449
- time .Sleep (time .Second )
450
- require .Equal (t , int64 (0 ), atomic .LoadInt64 (& callbackCount )) // No new callback
434
+ require .Equal (t , int64 (0 ), mockClient .getLoginCount ())
435
+
436
+ time .Sleep (200 * time .Millisecond )
437
+ require .Equal (t , int64 (0 ), atomic .LoadInt64 (& callbackCount ))
451
438
})
452
439
}
0 commit comments