From 18a17e1b945377102ba49354207c5e915873407d Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Fri, 29 Nov 2019 13:58:33 +0100 Subject: [PATCH] some tests --- pkg/op/authrequest.go | 6 +- pkg/op/authrequest_test.go | 176 ++++++++++++++++++++++++++----------- pkg/op/mock/client.go | 29 ++++++ pkg/op/mock/client.mock.go | 76 ++++++++++++++++ pkg/op/mock/generate.go | 1 + 5 files changed, 233 insertions(+), 55 deletions(-) create mode 100644 pkg/op/mock/client.go create mode 100644 pkg/op/mock/client.mock.go diff --git a/pkg/op/authrequest.go b/pkg/op/authrequest.go index 7bf557b..6ec84a2 100644 --- a/pkg/op/authrequest.go +++ b/pkg/op/authrequest.go @@ -69,7 +69,7 @@ func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) { AuthRequestError(w, r, req, err) return } - RedirectToLogin(req, client, w, r) + RedirectToLogin(req.GetID(), client, w, r) } func ValidateAuthRequest(authReq *oidc.AuthRequest, storage Storage) error { @@ -133,8 +133,8 @@ func ValidateAuthReqRedirectURI(uri, client_id string, responseType oidc.Respons return nil } -func RedirectToLogin(authReq AuthRequest, client Client, w http.ResponseWriter, r *http.Request) { - login := client.LoginURL(authReq.GetID()) +func RedirectToLogin(authReqID string, client Client, w http.ResponseWriter, r *http.Request) { + login := client.LoginURL(authReqID) http.Redirect(w, r, login, http.StatusFound) } diff --git a/pkg/op/authrequest_test.go b/pkg/op/authrequest_test.go index 2cbc665..2374aa6 100644 --- a/pkg/op/authrequest_test.go +++ b/pkg/op/authrequest_test.go @@ -6,11 +6,66 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" + "github.com/caos/oidc/pkg/oidc" "github.com/caos/oidc/pkg/op" "github.com/caos/oidc/pkg/op/mock" ) +func TestAuthorize(t *testing.T) { + // testCallback := func(t *testing.T, clienID string) callbackHandler { + // return func(authReq *oidc.AuthRequest, client oidc.Client, w http.ResponseWriter, r *http.Request) { + // // require.Equal(t, clientID, client.) + // } + // } + // testErr := func(t *testing.T, expected error) errorHandler { + // return func(w http.ResponseWriter, r *http.Request, authReq *oidc.AuthRequest, err error) { + // require.Equal(t, expected, err) + // } + // } + type args struct { + w http.ResponseWriter + r *http.Request + authorizer op.Authorizer + } + tests := []struct { + name string + args args + }{ + { + "parsing fails", + args{ + httptest.NewRecorder(), + &http.Request{Method: "POST", Body: nil}, + mock.NewAuthorizerExpectValid(t, true), + // testCallback(t, ""), + // testErr(t, ErrInvalidRequest("cannot parse form")), + }, + }, + { + "decoding fails", + args{ + httptest.NewRecorder(), + func() *http.Request { + r := httptest.NewRequest("POST", "/authorize", strings.NewReader("client_id=foo")) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + return r + }(), + mock.NewAuthorizerExpectValid(t, true), + // testCallback(t, ""), + // testErr(t, ErrInvalidRequest("cannot parse auth request")), + }, + }, + // {"decoding fails", args{httptest.NewRecorder(), &http.Request{}, mock.NewAuthorizerExpectValid(t), nil, testErr(t, nil)}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + op.Authorize(tt.args.w, tt.args.r, tt.args.authorizer) + }) + } +} + func TestValidateAuthRequest(t *testing.T) { type args struct { authRequest *oidc.AuthRequest @@ -60,6 +115,34 @@ func TestValidateAuthRequest(t *testing.T) { } } +func TestValidateAuthReqScopes(t *testing.T) { + type args struct { + scopes []string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + "scopes missing fails", args{}, true, + }, + { + "scope openid missing fails", args{[]string{"email"}}, true, + }, + { + "scope ok", args{[]string{"openid"}}, false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := op.ValidateAuthReqScopes(tt.args.scopes); (err != nil) != tt.wantErr { + t.Errorf("ValidateAuthReqScopes() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + func TestValidateAuthReqRedirectURI(t *testing.T) { type args struct { uri string @@ -142,45 +225,38 @@ func TestValidateAuthReqRedirectURI(t *testing.T) { } } -func TestValidateAuthReqScopes(t *testing.T) { +func TestRedirectToLogin(t *testing.T) { type args struct { - scopes []string + authReqID string + client op.Client + w http.ResponseWriter + r *http.Request } tests := []struct { - name string - args args - wantErr bool + name string + args args }{ { - "scopes missing fails", args{}, true, - }, - { - "scope openid missing fails", args{[]string{"email"}}, true, - }, - { - "scope ok", args{[]string{"openid"}}, false, + "redirect ok", + args{ + "id", + mock.NewClientExpectAny(t, op.ApplicationTypeNative), + httptest.NewRecorder(), + httptest.NewRequest("GET", "/authorize", nil), + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := op.ValidateAuthReqScopes(tt.args.scopes); (err != nil) != tt.wantErr { - t.Errorf("ValidateAuthReqScopes() error = %v, wantErr %v", err, tt.wantErr) - } + op.RedirectToLogin(tt.args.authReqID, tt.args.client, tt.args.w, tt.args.r) + rec := tt.args.w.(*httptest.ResponseRecorder) + require.Equal(t, http.StatusFound, rec.Code) + require.Equal(t, "/login?id=id", rec.Header().Get("location")) }) } } -func TestAuthorize(t *testing.T) { - // testCallback := func(t *testing.T, clienID string) callbackHandler { - // return func(authReq *oidc.AuthRequest, client oidc.Client, w http.ResponseWriter, r *http.Request) { - // // require.Equal(t, clientID, client.) - // } - // } - // testErr := func(t *testing.T, expected error) errorHandler { - // return func(w http.ResponseWriter, r *http.Request, authReq *oidc.AuthRequest, err error) { - // require.Equal(t, expected, err) - // } - // } +func TestAuthorizeCallback(t *testing.T) { type args struct { w http.ResponseWriter r *http.Request @@ -190,35 +266,31 @@ func TestAuthorize(t *testing.T) { name string args args }{ - { - "parsing fails", - args{ - httptest.NewRecorder(), - &http.Request{Method: "POST", Body: nil}, - mock.NewAuthorizerExpectValid(t, true), - // testCallback(t, ""), - // testErr(t, ErrInvalidRequest("cannot parse form")), - }, - }, - { - "decoding fails", - args{ - httptest.NewRecorder(), - func() *http.Request { - r := httptest.NewRequest("POST", "/authorize", strings.NewReader("client_id=foo")) - r.Header.Set("Content-Type", "application/x-www-form-urlencoded") - return r - }(), - mock.NewAuthorizerExpectValid(t, true), - // testCallback(t, ""), - // testErr(t, ErrInvalidRequest("cannot parse auth request")), - }, - }, - // {"decoding fails", args{httptest.NewRecorder(), &http.Request{}, mock.NewAuthorizerExpectValid(t), nil, testErr(t, nil)}}, + // TODO: Add test cases. } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - op.Authorize(tt.args.w, tt.args.r, tt.args.authorizer) + op.AuthorizeCallback(tt.args.w, tt.args.r, tt.args.authorizer) + }) + } +} + +func TestAuthResponse(t *testing.T) { + type args struct { + authReq op.AuthRequest + authorizer op.Authorizer + w http.ResponseWriter + r *http.Request + } + tests := []struct { + name string + args args + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + op.AuthResponse(tt.args.authReq, tt.args.authorizer, tt.args.w, tt.args.r) }) } } diff --git a/pkg/op/mock/client.go b/pkg/op/mock/client.go new file mode 100644 index 0000000..242eb13 --- /dev/null +++ b/pkg/op/mock/client.go @@ -0,0 +1,29 @@ +package mock + +import ( + "testing" + + gomock "github.com/golang/mock/gomock" + + op "github.com/caos/oidc/pkg/op" +) + +func NewClient(t *testing.T) op.Client { + return NewMockClient(gomock.NewController(t)) +} + +func NewClientExpectAny(t *testing.T, appType op.ApplicationType) op.Client { + c := NewClient(t) + m := c.(*MockClient) + m.EXPECT().RedirectURIs().AnyTimes().Return([]string{ + "https://registered.com/callback", + "http://registered.com/callback", + "http://localhost:9999/callback", + "custom://callback"}) + m.EXPECT().ApplicationType().AnyTimes().Return(appType) + m.EXPECT().LoginURL(gomock.Any()).AnyTimes().DoAndReturn( + func(id string) string { + return "login?id=" + id + }) + return c +} diff --git a/pkg/op/mock/client.mock.go b/pkg/op/mock/client.mock.go new file mode 100644 index 0000000..87c3575 --- /dev/null +++ b/pkg/op/mock/client.mock.go @@ -0,0 +1,76 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/caos/oidc/pkg/op (interfaces: Client) + +// Package mock is a generated GoMock package. +package mock + +import ( + op "github.com/caos/oidc/pkg/op" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockClient is a mock of Client interface +type MockClient struct { + ctrl *gomock.Controller + recorder *MockClientMockRecorder +} + +// MockClientMockRecorder is the mock recorder for MockClient +type MockClientMockRecorder struct { + mock *MockClient +} + +// NewMockClient creates a new mock instance +func NewMockClient(ctrl *gomock.Controller) *MockClient { + mock := &MockClient{ctrl: ctrl} + mock.recorder = &MockClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockClient) EXPECT() *MockClientMockRecorder { + return m.recorder +} + +// ApplicationType mocks base method +func (m *MockClient) ApplicationType() op.ApplicationType { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ApplicationType") + ret0, _ := ret[0].(op.ApplicationType) + return ret0 +} + +// ApplicationType indicates an expected call of ApplicationType +func (mr *MockClientMockRecorder) ApplicationType() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplicationType", reflect.TypeOf((*MockClient)(nil).ApplicationType)) +} + +// LoginURL mocks base method +func (m *MockClient) LoginURL(arg0 string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoginURL", arg0) + ret0, _ := ret[0].(string) + return ret0 +} + +// LoginURL indicates an expected call of LoginURL +func (mr *MockClientMockRecorder) LoginURL(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoginURL", reflect.TypeOf((*MockClient)(nil).LoginURL), arg0) +} + +// RedirectURIs mocks base method +func (m *MockClient) RedirectURIs() []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RedirectURIs") + ret0, _ := ret[0].([]string) + return ret0 +} + +// RedirectURIs indicates an expected call of RedirectURIs +func (mr *MockClientMockRecorder) RedirectURIs() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RedirectURIs", reflect.TypeOf((*MockClient)(nil).RedirectURIs)) +} diff --git a/pkg/op/mock/generate.go b/pkg/op/mock/generate.go index 330b025..869be81 100644 --- a/pkg/op/mock/generate.go +++ b/pkg/op/mock/generate.go @@ -2,3 +2,4 @@ package mock //go:generate mockgen -package mock -destination ./storage.mock.go github.com/caos/oidc/pkg/op Storage //go:generate mockgen -package mock -destination ./authorizer.mock.go github.com/caos/oidc/pkg/op Authorizer +//go:generate mockgen -package mock -destination ./client.mock.go github.com/caos/oidc/pkg/op Client