Skip to content

Commit 27c010d

Browse files
committed
add auth_token_async_test.go
1 parent cdefe0c commit 27c010d

File tree

1 file changed

+56
-151
lines changed

1 file changed

+56
-151
lines changed

auth/auth_test.go

Lines changed: 56 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"net/http"
2323
"net/http/httptest"
2424
"strings"
25-
"sync"
2625
"testing"
2726
"time"
2827

@@ -106,9 +105,9 @@ func TestError_Temporary(t *testing.T) {
106105

107106
func TestToken_MetadataString(t *testing.T) {
108107
cases := []struct {
109-
name string
108+
name string
110109
metadata map[string]interface{}
111-
want string
110+
want string
112111
}{
113112
{
114113
name: "nil metadata",
@@ -143,10 +142,10 @@ func TestToken_isValidWithEarlyExpiry(t *testing.T) {
143142
defer func() { timeNow = time.Now }()
144143

145144
cases := []struct {
146-
name string
147-
tok *Token
145+
name string
146+
tok *Token
148147
expiry time.Duration
149-
want bool
148+
want bool
150149
}{
151150
{name: "4 minutes", tok: &Token{Expiry: now.Add(4 * 60 * time.Second)}, expiry: defaultExpiryDelta, want: true},
152151
{name: "3 minutes and 45 seconds", tok: &Token{Expiry: now.Add(defaultExpiryDelta)}, expiry: defaultExpiryDelta, want: true},
@@ -170,12 +169,12 @@ func TestError_Error(t *testing.T) {
170169
tests := []struct {
171170
name string
172171

173-
Response *http.Response
174-
Body []byte
175-
Err error
176-
code string
172+
Response *http.Response
173+
Body []byte
174+
Err error
175+
code string
177176
description string
178-
uri string
177+
uri string
179178

180179
want string
181180
}{
@@ -188,22 +187,22 @@ func TestError_Error(t *testing.T) {
188187
want: "auth: cannot fetch token: 418\nResponse: I'm a teapot",
189188
},
190189
{
191-
name: "from query",
192-
code: fmt.Sprint(http.StatusTeapot),
190+
name: "from query",
191+
code: fmt.Sprint(http.StatusTeapot),
193192
description: "I'm a teapot",
194-
uri: "somewhere",
195-
want: "auth: \"418\" \"I'm a teapot\" \"somewhere\"",
193+
uri: "somewhere",
194+
want: "auth: \"418\" \"I'm a teapot\" \"somewhere\"",
196195
},
197196
}
198197
for _, tt := range tests {
199198
t.Run(tt.name, func(t *testing.T) {
200199
r := &Error{
201-
Response: tt.Response,
202-
Body: tt.Body,
203-
Err: tt.Err,
204-
code: tt.code,
200+
Response: tt.Response,
201+
Body: tt.Body,
202+
Err: tt.Err,
203+
code: tt.code,
205204
description: tt.description,
206-
uri: tt.uri,
205+
uri: tt.uri,
207206
}
208207
if got := r.Error(); got != tt.want {
209208
t.Errorf("Error.Error() = %v, want %v", got, tt.want)
@@ -225,9 +224,9 @@ func TestNew2LOTokenProvider_JSONResponse(t *testing.T) {
225224
defer ts.Close()
226225

227226
opts := &Options2LO{
228-
Email: "aaa@example.com",
227+
Email: "aaa@example.com",
229228
PrivateKey: fakePrivateKey,
230-
TokenURL: ts.URL,
229+
TokenURL: ts.URL,
231230
}
232231
tp, err := New2LOTokenProvider(opts)
233232
if err != nil {
@@ -263,9 +262,9 @@ func TestNew2LOTokenProvider_BadResponse(t *testing.T) {
263262
defer ts.Close()
264263

265264
opts := &Options2LO{
266-
Email: "aaa@example.com",
265+
Email: "aaa@example.com",
267266
PrivateKey: fakePrivateKey,
268-
TokenURL: ts.URL,
267+
TokenURL: ts.URL,
269268
}
270269
tp, err := New2LOTokenProvider(opts)
271270
if err != nil {
@@ -300,9 +299,9 @@ func TestNew2LOTokenProvider_BadResponseType(t *testing.T) {
300299
}))
301300
defer ts.Close()
302301
opts := &Options2LO{
303-
Email: "aaa@example.com",
302+
Email: "aaa@example.com",
304303
PrivateKey: fakePrivateKey,
305-
TokenURL: ts.URL,
304+
TokenURL: ts.URL,
306305
}
307306
tp, err := New2LOTokenProvider(opts)
308307
if err != nil {
@@ -334,10 +333,10 @@ func TestNew2LOTokenProvider_Assertion(t *testing.T) {
334333
defer ts.Close()
335334

336335
opts := &Options2LO{
337-
Email: "aaa@example.com",
338-
PrivateKey: fakePrivateKey,
336+
Email: "aaa@example.com",
337+
PrivateKey: fakePrivateKey,
339338
PrivateKeyID: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
340-
TokenURL: ts.URL,
339+
TokenURL: ts.URL,
341340
}
342341

343342
tp, err := New2LOTokenProvider(opts)
@@ -365,8 +364,8 @@ func TestNew2LOTokenProvider_Assertion(t *testing.T) {
365364

366365
want := jwt.Header{
367366
Algorithm: "RS256",
368-
Type: "JWT",
369-
KeyID: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
367+
Type: "JWT",
368+
KeyID: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
370369
}
371370
if got != want {
372371
t.Errorf("access token header = %q; want %q", got, want)
@@ -391,23 +390,23 @@ func TestNew2LOTokenProvider_AssertionPayload(t *testing.T) {
391390

392391
for _, opts := range []*Options2LO{
393392
{
394-
Email: "aaa1@example.com",
395-
PrivateKey: fakePrivateKey,
393+
Email: "aaa1@example.com",
394+
PrivateKey: fakePrivateKey,
396395
PrivateKeyID: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
397-
TokenURL: ts.URL,
396+
TokenURL: ts.URL,
398397
},
399398
{
400-
Email: "aaa2@example.com",
401-
PrivateKey: fakePrivateKey,
399+
Email: "aaa2@example.com",
400+
PrivateKey: fakePrivateKey,
402401
PrivateKeyID: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
403-
TokenURL: ts.URL,
404-
Audience: "https://example.com",
402+
TokenURL: ts.URL,
403+
Audience: "https://example.com",
405404
},
406405
{
407-
Email: "aaa2@example.com",
408-
PrivateKey: fakePrivateKey,
406+
Email: "aaa2@example.com",
407+
PrivateKey: fakePrivateKey,
409408
PrivateKeyID: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
410-
TokenURL: ts.URL,
409+
TokenURL: ts.URL,
411410
PrivateClaims: map[string]interface{}{
412411
"private0": "claim0",
413412
"private1": "claim1",
@@ -479,9 +478,9 @@ func TestNew2LOTokenProvider_TokenError(t *testing.T) {
479478
defer ts.Close()
480479

481480
opts := &Options2LO{
482-
Email: "aaa@example.com",
481+
Email: "aaa@example.com",
483482
PrivateKey: fakePrivateKey,
484-
TokenURL: ts.URL,
483+
TokenURL: ts.URL,
485484
}
486485

487486
tp, err := New2LOTokenProvider(opts)
@@ -514,20 +513,20 @@ func TestNew2LOTokenProvider_Validate(t *testing.T) {
514513
name: "missing email",
515514
opts: &Options2LO{
516515
PrivateKey: []byte("key"),
517-
TokenURL: "url",
516+
TokenURL: "url",
518517
},
519518
},
520519
{
521520
name: "missing key",
522521
opts: &Options2LO{
523-
Email: "email",
522+
Email: "email",
524523
TokenURL: "url",
525524
},
526525
},
527526
{
528527
name: "missing URL",
529528
opts: &Options2LO{
530-
Email: "email",
529+
Email: "email",
531530
PrivateKey: []byte("key"),
532531
},
533532
},
@@ -616,25 +615,25 @@ func TestComputeTokenProvider_NonBlockingRefresh(t *testing.T) {
616615

617616
func TestComputeTokenProvider_BlockingRefresh(t *testing.T) {
618617
tests := []struct {
619-
name string
618+
name string
620619
disableAutoRefresh bool
621-
want1 string
622-
want2 string
623-
wantState2 tokenState
620+
want1 string
621+
want2 string
622+
wantState2 tokenState
624623
}{
625624
{
626-
name: "disableAutoRefresh",
625+
name: "disableAutoRefresh",
627626
disableAutoRefresh: true,
628-
want1: "1",
629-
want2: "1",
627+
want1: "1",
628+
want2: "1",
630629
// Because token "count" does not increase, it will always be stale.
631630
wantState2: stale,
632631
},
633632
{
634-
name: "autoRefresh",
633+
name: "autoRefresh",
635634
disableAutoRefresh: false,
636-
want1: "1",
637-
want2: "2",
635+
want1: "1",
636+
want2: "2",
638637
// As token "count" increases to 2, it transitions to fresh.
639638
wantState2: fresh,
640639
},
@@ -647,7 +646,7 @@ func TestComputeTokenProvider_BlockingRefresh(t *testing.T) {
647646
defer func() { timeNow = time.Now }()
648647
tp := NewCachedTokenProvider(&countingTestProvider{count: 1}, &CachedTokenProviderOptions{
649648
DisableAsyncRefresh: true,
650-
DisableAutoRefresh: tt.disableAutoRefresh,
649+
DisableAutoRefresh: tt.disableAutoRefresh,
651650
// EarlyTokenRefresh ensures that token with early expiry just less than 2 seconds before now is already stale.
652651
ExpireEarly: 1990 * time.Millisecond,
653652
})
@@ -681,97 +680,3 @@ func TestComputeTokenProvider_BlockingRefresh(t *testing.T) {
681680
})
682681
}
683682
}
684-
685-
type controllableTokenProvider struct {
686-
mu sync.Mutex
687-
count int
688-
tok *Token
689-
err error
690-
block chan struct{}
691-
}
692-
693-
func (p *controllableTokenProvider) Token(ctx context.Context) (*Token, error) {
694-
if ch := p.getBlockChan(); ch != nil {
695-
<-ch
696-
}
697-
p.mu.Lock()
698-
defer p.mu.Unlock()
699-
p.count++
700-
return p.tok, p.err
701-
}
702-
703-
func (p *controllableTokenProvider) getBlockChan() chan struct{} {
704-
p.mu.Lock()
705-
defer p.mu.Unlock()
706-
return p.block
707-
}
708-
709-
func (p *controllableTokenProvider) setBlockChan(ch chan struct{}) {
710-
p.mu.Lock()
711-
defer p.mu.Unlock()
712-
p.block = ch
713-
}
714-
715-
func (p *controllableTokenProvider) getCount() int {
716-
p.mu.Lock()
717-
defer p.mu.Unlock()
718-
return p.count
719-
}
720-
721-
func TestCachedTokenProvider_TokenAsyncRace(t *testing.T) {
722-
now := time.Now()
723-
timeNow = func() time.Time { return now }
724-
defer func() { timeNow = time.Now }()
725-
726-
tp := &controllableTokenProvider{}
727-
ctp := NewCachedTokenProvider(tp, &CachedTokenProviderOptions{
728-
ExpireEarly: 2 * time.Second,
729-
}).(*cachedTokenProvider)
730-
731-
// 1. Cache a stale token.
732-
tp.tok = &Token{Value: "initial", Expiry: now.Add(1 * time.Second)}
733-
if _, err := ctp.Token(context.Background()); err != nil {
734-
t.Fatalf("initial Token() failed: %v", err)
735-
}
736-
if got, want := tp.getCount(), 1; got != want {
737-
t.Fatalf("tp.count = %d; want %d", got, want)
738-
}
739-
if got, want := ctp.tokenState(), stale; got != want {
740-
t.Fatalf("tokenState = %v; want %v", got, want)
741-
}
742-
743-
// 2. Setup for refresh.
744-
tp.setBlockChan(make(chan struct{}))
745-
tp.tok = &Token{Value: "refreshed", Expiry: now.Add(1 * time.Hour)}
746-
747-
// 3. Concurrently call Token to trigger async refresh.
748-
var wg sync.WaitGroup
749-
for i := 0; i < 10; i++ {
750-
wg.Add(1)
751-
go func() {
752-
defer wg.Done()
753-
ctp.Token(context.Background())
754-
}()
755-
}
756-
757-
// 4. Unblock refresh and wait for all goroutines to finish.
758-
time.Sleep(100 * time.Millisecond) // give time for goroutines to run
759-
close(tp.getBlockChan())
760-
wg.Wait()
761-
time.Sleep(100 * time.Millisecond) // give time for async refresh to complete
762-
763-
// 5. Check results.
764-
if got, want := tp.getCount(), 2; got != want {
765-
t.Errorf("tp.count = %d; want %d", got, want)
766-
}
767-
if got, want := ctp.tokenState(), fresh; got != want {
768-
t.Errorf("tokenState = %v; want %v", got, want)
769-
}
770-
tok, err := ctp.Token(context.Background())
771-
if err != nil {
772-
t.Fatal(err)
773-
}
774-
if got, want := tok.Value, "refreshed"; got != want {
775-
t.Errorf("tok.Value = %q; want %q", got, want)
776-
}
777-
}

0 commit comments

Comments
 (0)