Skip to content

Commit 7bf9f41

Browse files
authored
Refactor test code (#48)
* Refactor: close channel in server goroutine * Refactor: enable verbose logging * Refactor: remove doAuthCodeFlow() * Refactor: replace errgroup.Group with sync.WaitGroup
1 parent ef51a15 commit 7bf9f41

File tree

5 files changed

+393
-285
lines changed

5 files changed

+393
-285
lines changed

e2e_test/client/client.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import (
66
"fmt"
77
"io/ioutil"
88
"net/http"
9+
"testing"
10+
11+
"github.com/google/go-cmp/cmp"
912
)
1013

1114
var certPool = x509.NewCertPool()
@@ -33,3 +36,17 @@ func Get(url string) (int, string, error) {
3336
}
3437
return resp.StatusCode, string(b), nil
3538
}
39+
40+
func GetAndVerify(t *testing.T, url string, code int, body string) {
41+
gotCode, gotBody, err := Get(url)
42+
if err != nil {
43+
t.Errorf("could not open browser request: %s", err)
44+
return
45+
}
46+
if gotCode != code {
47+
t.Errorf("status wants %d but %d", code, gotCode)
48+
}
49+
if gotBody != body {
50+
t.Errorf("response body did not match: %s", cmp.Diff(gotBody, body))
51+
}
52+
}

e2e_test/e2e_test.go

Lines changed: 127 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -6,139 +6,162 @@ import (
66
"net/http"
77
"net/http/httptest"
88
"strings"
9+
"sync"
910
"testing"
1011
"time"
1112

1213
"github.com/int128/oauth2cli"
1314
"github.com/int128/oauth2cli/e2e_test/authserver"
1415
"github.com/int128/oauth2cli/e2e_test/client"
1516
"golang.org/x/oauth2"
16-
"golang.org/x/sync/errgroup"
1717
)
1818

1919
const invalidGrantResponse = `{"error":"invalid_grant"}`
2020
const validTokenResponse = `{"access_token": "ACCESS_TOKEN","token_type": "Bearer","expires_in": 3600,"refresh_token": "REFRESH_TOKEN"}`
2121

2222
func TestHappyPath(t *testing.T) {
23-
cfg := oauth2cli.Config{
24-
OAuth2Config: oauth2.Config{
25-
ClientID: "YOUR_CLIENT_ID",
26-
ClientSecret: "YOUR_CLIENT_SECRET",
27-
Scopes: []string{"email", "profile"},
28-
},
29-
}
30-
h := &authserver.Handler{
31-
T: t,
32-
NewAuthorizationResponse: func(r authserver.AuthorizationRequest) string {
33-
if w := "email profile"; r.Scope != w {
34-
t.Errorf("scope wants %s but %s", w, r.Scope)
35-
return fmt.Sprintf("%s?error=invalid_scope", r.RedirectURI)
36-
}
37-
redirectURIPrefix := "http://localhost:"
38-
if !strings.HasPrefix(r.RedirectURI, redirectURIPrefix) {
39-
t.Errorf("redirect_uri wants prefix %s but was %s", redirectURIPrefix, r.RedirectURI)
40-
return fmt.Sprintf("%s?error=invalid_redirect_uri", r.RedirectURI)
41-
}
42-
return fmt.Sprintf("%s?state=%s&code=%s", r.RedirectURI, r.State, "AUTH_CODE")
43-
},
44-
NewTokenResponse: func(r authserver.TokenRequest) (int, string) {
45-
if w := "AUTH_CODE"; r.Code != w {
46-
t.Errorf("code wants %s but %s", w, r.Code)
47-
return 400, invalidGrantResponse
48-
}
49-
return 200, validTokenResponse
50-
},
51-
}
52-
doAuthCodeFlow(t, cfg, h)
23+
ctx, cancel := context.WithTimeout(context.TODO(), 1*time.Second)
24+
defer cancel()
25+
openBrowserCh := make(chan string)
26+
var wg sync.WaitGroup
27+
wg.Add(1)
28+
go func() {
29+
defer wg.Done()
30+
defer close(openBrowserCh)
31+
// Start a local server and get a token.
32+
s := httptest.NewServer(&authserver.Handler{
33+
T: t,
34+
NewAuthorizationResponse: func(r authserver.AuthorizationRequest) string {
35+
if w := "email profile"; r.Scope != w {
36+
t.Errorf("scope wants %s but %s", w, r.Scope)
37+
return fmt.Sprintf("%s?error=invalid_scope", r.RedirectURI)
38+
}
39+
redirectURIPrefix := "http://localhost:"
40+
if !strings.HasPrefix(r.RedirectURI, redirectURIPrefix) {
41+
t.Errorf("redirect_uri wants prefix %s but was %s", redirectURIPrefix, r.RedirectURI)
42+
return fmt.Sprintf("%s?error=invalid_redirect_uri", r.RedirectURI)
43+
}
44+
return fmt.Sprintf("%s?state=%s&code=%s", r.RedirectURI, r.State, "AUTH_CODE")
45+
},
46+
NewTokenResponse: func(r authserver.TokenRequest) (int, string) {
47+
if w := "AUTH_CODE"; r.Code != w {
48+
t.Errorf("code wants %s but %s", w, r.Code)
49+
return 400, invalidGrantResponse
50+
}
51+
return 200, validTokenResponse
52+
},
53+
})
54+
defer s.Close()
55+
cfg := oauth2cli.Config{
56+
OAuth2Config: oauth2.Config{
57+
ClientID: "YOUR_CLIENT_ID",
58+
ClientSecret: "YOUR_CLIENT_SECRET",
59+
Scopes: []string{"email", "profile"},
60+
Endpoint: oauth2.Endpoint{
61+
AuthURL: s.URL + "/auth",
62+
TokenURL: s.URL + "/token",
63+
},
64+
},
65+
LocalServerReadyChan: openBrowserCh,
66+
LocalServerMiddleware: loggingMiddleware(t),
67+
Logf: t.Logf,
68+
}
69+
token, err := oauth2cli.GetToken(ctx, cfg)
70+
if err != nil {
71+
t.Errorf("could not get a token: %s", err)
72+
return
73+
}
74+
if "ACCESS_TOKEN" != token.AccessToken {
75+
t.Errorf("AccessToken wants %s but %s", "ACCESS_TOKEN", token.AccessToken)
76+
}
77+
if "REFRESH_TOKEN" != token.RefreshToken {
78+
t.Errorf("RefreshToken wants %s but %s", "REFRESH_TOKEN", token.AccessToken)
79+
}
80+
}()
81+
wg.Add(1)
82+
go func() {
83+
defer wg.Done()
84+
toURL, ok := <-openBrowserCh
85+
if !ok {
86+
t.Errorf("server already closed")
87+
return
88+
}
89+
client.GetAndVerify(t, toURL, 200, oauth2cli.DefaultLocalServerSuccessHTML)
90+
}()
91+
wg.Wait()
5392
}
5493

5594
func TestRedirectURLHostname(t *testing.T) {
56-
cfg := oauth2cli.Config{
57-
OAuth2Config: oauth2.Config{
58-
ClientID: "YOUR_CLIENT_ID",
59-
ClientSecret: "YOUR_CLIENT_SECRET",
60-
Scopes: []string{"email", "profile"},
61-
},
62-
RedirectURLHostname: "127.0.0.1",
63-
}
64-
h := &authserver.Handler{
65-
T: t,
66-
NewAuthorizationResponse: func(r authserver.AuthorizationRequest) string {
67-
if w := "email profile"; r.Scope != w {
68-
t.Errorf("scope wants %s but %s", w, r.Scope)
69-
return fmt.Sprintf("%s?error=invalid_scope", r.RedirectURI)
70-
}
71-
redirectURIPrefix := "http://127.0.0.1:"
72-
if !strings.HasPrefix(r.RedirectURI, redirectURIPrefix) {
73-
t.Errorf("redirect_uri wants prefix %s but was %s", redirectURIPrefix, r.RedirectURI)
74-
return fmt.Sprintf("%s?error=invalid_redirect_uri", r.RedirectURI)
75-
}
76-
return fmt.Sprintf("%s?state=%s&code=%s", r.RedirectURI, r.State, "AUTH_CODE")
77-
},
78-
NewTokenResponse: func(r authserver.TokenRequest) (int, string) {
79-
if w := "AUTH_CODE"; r.Code != w {
80-
t.Errorf("code wants %s but %s", w, r.Code)
81-
return 400, invalidGrantResponse
82-
}
83-
return 200, validTokenResponse
84-
},
85-
}
86-
doAuthCodeFlow(t, cfg, h)
87-
}
88-
89-
func doAuthCodeFlow(t *testing.T, cfg oauth2cli.Config, h *authserver.Handler) {
9095
ctx, cancel := context.WithTimeout(context.TODO(), 1*time.Second)
9196
defer cancel()
92-
s := httptest.NewServer(h)
93-
defer s.Close()
9497
openBrowserCh := make(chan string)
95-
defer close(openBrowserCh)
96-
97-
cfg.LocalServerReadyChan = openBrowserCh
98-
cfg.OAuth2Config.Endpoint = oauth2.Endpoint{
99-
AuthURL: s.URL + "/auth",
100-
TokenURL: s.URL + "/token",
101-
}
102-
cfg.LocalServerMiddleware = loggingMiddleware(t)
103-
104-
eg, ctx := errgroup.WithContext(ctx)
105-
eg.Go(func() error {
106-
// Wait for the local server and open a browser request.
107-
select {
108-
case to := <-openBrowserCh:
109-
status, body, err := client.Get(to)
110-
if err != nil {
111-
return fmt.Errorf("could not open browser request: %w", err)
112-
}
113-
t.Logf("got response body: %s", body)
114-
if status != 200 {
115-
t.Errorf("status wants 200 but %d", status)
116-
}
117-
if body != oauth2cli.DefaultLocalServerSuccessHTML {
118-
t.Errorf("response body did not match")
119-
}
120-
return nil
121-
case <-ctx.Done():
122-
return fmt.Errorf("context done while waiting for opening browser: %w", ctx.Err())
123-
}
124-
})
125-
eg.Go(func() error {
98+
var wg sync.WaitGroup
99+
wg.Add(1)
100+
go func() {
101+
defer wg.Done()
102+
defer close(openBrowserCh)
126103
// Start a local server and get a token.
104+
s := httptest.NewServer(&authserver.Handler{
105+
T: t,
106+
NewAuthorizationResponse: func(r authserver.AuthorizationRequest) string {
107+
if w := "email profile"; r.Scope != w {
108+
t.Errorf("scope wants %s but %s", w, r.Scope)
109+
return fmt.Sprintf("%s?error=invalid_scope", r.RedirectURI)
110+
}
111+
redirectURIPrefix := "http://127.0.0.1:"
112+
if !strings.HasPrefix(r.RedirectURI, redirectURIPrefix) {
113+
t.Errorf("redirect_uri wants prefix %s but was %s", redirectURIPrefix, r.RedirectURI)
114+
return fmt.Sprintf("%s?error=invalid_redirect_uri", r.RedirectURI)
115+
}
116+
return fmt.Sprintf("%s?state=%s&code=%s", r.RedirectURI, r.State, "AUTH_CODE")
117+
},
118+
NewTokenResponse: func(r authserver.TokenRequest) (int, string) {
119+
if w := "AUTH_CODE"; r.Code != w {
120+
t.Errorf("code wants %s but %s", w, r.Code)
121+
return 400, invalidGrantResponse
122+
}
123+
return 200, validTokenResponse
124+
},
125+
})
126+
defer s.Close()
127+
cfg := oauth2cli.Config{
128+
OAuth2Config: oauth2.Config{
129+
ClientID: "YOUR_CLIENT_ID",
130+
ClientSecret: "YOUR_CLIENT_SECRET",
131+
Scopes: []string{"email", "profile"},
132+
Endpoint: oauth2.Endpoint{
133+
AuthURL: s.URL + "/auth",
134+
TokenURL: s.URL + "/token",
135+
},
136+
},
137+
RedirectURLHostname: "127.0.0.1",
138+
LocalServerReadyChan: openBrowserCh,
139+
LocalServerMiddleware: loggingMiddleware(t),
140+
Logf: t.Logf,
141+
}
127142
token, err := oauth2cli.GetToken(ctx, cfg)
128143
if err != nil {
129-
return fmt.Errorf("could not get a token: %w", err)
144+
t.Errorf("could not get a token: %s", err)
145+
return
130146
}
131147
if "ACCESS_TOKEN" != token.AccessToken {
132148
t.Errorf("AccessToken wants %s but %s", "ACCESS_TOKEN", token.AccessToken)
133149
}
134150
if "REFRESH_TOKEN" != token.RefreshToken {
135151
t.Errorf("RefreshToken wants %s but %s", "REFRESH_TOKEN", token.AccessToken)
136152
}
137-
return nil
138-
})
139-
if err := eg.Wait(); err != nil {
140-
t.Errorf("error: %+v", err)
141-
}
153+
}()
154+
wg.Add(1)
155+
go func() {
156+
defer wg.Done()
157+
toURL, ok := <-openBrowserCh
158+
if !ok {
159+
t.Errorf("server already closed")
160+
return
161+
}
162+
client.GetAndVerify(t, toURL, 200, oauth2cli.DefaultLocalServerSuccessHTML)
163+
}()
164+
wg.Wait()
142165
}
143166

144167
func loggingMiddleware(t *testing.T) func(h http.Handler) http.Handler {

0 commit comments

Comments
 (0)