Skip to content

Commit 0c0bda5

Browse files
committed
improve concurrent test
1 parent 32abefa commit 0c0bda5

File tree

3 files changed

+31
-22
lines changed

3 files changed

+31
-22
lines changed

internal/mocks/mocks.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ var _ net.Error = (*Error)(nil)
133133
type TokenListener struct {
134134
// Mock implementation of the TokenManagerListener interface
135135
mock.Mock
136+
Id int32
136137
}
137138

138139
func (m *TokenListener) OnTokenNext(token *token.Token) {

manager/token_manager.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func NewTokenManager(idp shared.IdentityProvider, options TokenManagerOptions) (
114114
return &entraidTokenManager{
115115
idp: idp,
116116
token: nil,
117-
closedChan: make(chan struct{}),
117+
closedChan: nil,
118118
expirationRefreshRatio: options.ExpirationRefreshRatio,
119119
lowerRefreshBoundMs: options.LowerRefreshBoundMs,
120120
lowerBoundDuration: time.Duration(options.LowerRefreshBoundMs) * time.Millisecond,
@@ -217,13 +217,12 @@ func (e *entraidTokenManager) Start(listener TokenListener) (CancelFunc, error)
217217
if e.listener != nil {
218218
return nil, ErrTokenManagerAlreadyStarted
219219
}
220-
e.listener = listener
220+
221221
if e.closedChan != nil && !internal.IsClosed(e.closedChan) {
222222
// there is a hanging goroutine that is waiting for the closedChan to be closed
223223
// if the closedChan is not nil and not closed, close it
224224
close(e.closedChan)
225225
}
226-
e.closedChan = make(chan struct{})
227226

228227
t, err := e.GetToken(true)
229228
if err != nil {
@@ -233,6 +232,9 @@ func (e *entraidTokenManager) Start(listener TokenListener) (CancelFunc, error)
233232

234233
go listener.OnTokenNext(t)
235234

235+
e.closedChan = make(chan struct{})
236+
e.listener = listener
237+
236238
go func(listener TokenListener, closed <-chan struct{}) {
237239
maxDelay := time.Duration(e.retryOptions.MaxDelayMs) * time.Millisecond
238240
initialDelay := time.Duration(e.retryOptions.InitialDelayMs) * time.Millisecond
@@ -311,10 +313,7 @@ func (e *entraidTokenManager) Close() error {
311313
if e.closedChan == nil || e.listener == nil {
312314
return ErrTokenManagerAlreadyCanceled
313315
}
314-
315-
if e.listener != nil {
316-
e.listener = nil
317-
}
316+
e.listener = nil
318317
close(e.closedChan)
319318

320319
return nil

manager/token_manager_test.go

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -367,37 +367,47 @@ func TestTokenManager_Start(t *testing.T) {
367367
assert.NoError(t, err)
368368

369369
assert.NotPanics(t, func() {
370-
var last int32
370+
last := &atomic.Int32{}
371371
wg := &sync.WaitGroup{}
372372

373373
idp.On("RequestToken").Return(rawResponse, nil)
374374
mParser.On("ParseResponse", rawResponse).Return(testTokenValid, nil)
375375
listener.On("OnTokenNext", testTokenValid).Return()
376-
numExecutions := 50000
377-
for i := 0; i < numExecutions; i++ {
376+
numExecutions := int32(50000)
377+
for i := int32(0); i < numExecutions; i++ {
378378
wg.Add(1)
379-
go func(num int) {
379+
go func(num int32) {
380380
defer wg.Done()
381-
time.Sleep(time.Duration(int64(rand.Intn(100)) * int64(time.Millisecond)))
382381
var err error
382+
time.Sleep(time.Duration(int64(rand.Intn(1000)+(300-int(num)/2)) * int64(time.Millisecond)))
383+
last.Store(num)
383384
if num%2 == 0 {
384385
err = tokenManager.Close()
385386
} else {
386-
_, err = tokenManager.Start(listener)
387+
l := &mockTokenListener{Id: num}
388+
l.On("OnTokenNext", testTokenValid).Return()
389+
_, err = tokenManager.Start(l)
387390
}
388-
if err == nil {
389-
atomic.StoreInt32(&last, int32(num))
390-
} else if err != ErrTokenManagerAlreadyStarted && err != ErrTokenManagerAlreadyCanceled {
391-
log.Printf("Error: %v", err)
392-
t.Fail()
391+
if err != nil {
392+
if err != ErrTokenManagerAlreadyCanceled && err != ErrTokenManagerAlreadyStarted {
393+
// this is un unexpected error, fail the test
394+
assert.Error(t, err)
395+
}
393396
}
394397
}(i)
395398
}
396399
wg.Wait()
397-
lastExecution := atomic.LoadInt32(&last)
400+
lastExecution := last.Load()
398401
if lastExecution%2 == 0 {
402+
if tm.listener != nil {
403+
l := tm.listener.(*mockTokenListener)
404+
log.Printf("FAILING WITH lastExecution [STARTED]:[LISTENER:%d]: %d", l.Id, lastExecution)
405+
}
399406
assert.Nil(t, tm.listener)
400407
} else {
408+
if tm.listener == nil {
409+
log.Printf("FAILING WITH lastExecution[STOPPED]: %d", lastExecution)
410+
}
401411
assert.NotNil(t, tm.listener)
402412
cancel, err := tokenManager.Start(listener)
403413
assert.Nil(t, cancel)
@@ -606,7 +616,7 @@ func TestEntraidTokenManager_GetToken(t *testing.T) {
606616
cancel, err := tokenManager.Start(listener)
607617
assert.Error(t, err)
608618
assert.Nil(t, cancel)
609-
assert.NotNil(t, tm.listener)
619+
assert.Nil(t, tm.listener)
610620
})
611621
t.Run("GetToken with expired manager", func(t *testing.T) {
612622
t.Parallel()
@@ -1035,7 +1045,6 @@ func TestEntraidTokenManager_Streaming(t *testing.T) {
10351045
listener.On("OnTokenError", mock.Anything).Run(func(args mock.Arguments) {
10361046
err := args.Get(0)
10371047
assert.NotNil(t, err)
1038-
log.Printf("Found TOKEN Error: %v", err)
10391048
}).Return().Maybe()
10401049

10411050
cancel, err := tokenManager.Start(listener)
@@ -1109,7 +1118,7 @@ func TestEntraidTokenManager_Streaming(t *testing.T) {
11091118
assert.NotEqual(t, time.Duration(0), toRenewal)
11101119
assert.NotEqual(t, expiresIn, toRenewal)
11111120
assert.True(t, expiresIn > toRenewal)
1112-
<-time.After(toRenewal + 5*time.Millisecond)
1121+
<-time.After(toRenewal + 100*time.Millisecond)
11131122

11141123
idp.AssertNumberOfCalls(t, "RequestToken", 2)
11151124
listener.AssertNumberOfCalls(t, "OnTokenNext", 1)

0 commit comments

Comments
 (0)