1
0
mirror of https://github.com/volatiletech/authboss.git synced 2025-01-06 03:54:17 +02:00

Increase testing coverage.

- Missed some actual tests, added them.
- Added a bunch of useless tests to increase coverage. Guilty as
  charged.
This commit is contained in:
Aaron L 2018-05-14 14:27:33 -07:00
parent bf1eb39403
commit c38f79490b
11 changed files with 550 additions and 53 deletions

View File

@ -225,8 +225,8 @@ func (c *ClientStateResponseWriter) putClientState() error {
// logging a user out.
func DelKnownSession(w http.ResponseWriter) {
DelSession(w, SessionKey)
DelSession(w, SessionLastAction)
DelSession(w, SessionHalfAuthKey)
DelSession(w, SessionLastAction)
}
// DelKnownCookie deletes all known cookie variables, which can be used

View File

@ -159,3 +159,40 @@ func TestFlashClearer(t *testing.T) {
t.Error("event was wrong", got)
}
}
func TestDelKnown(t *testing.T) {
t.Parallel()
csrw := &ClientStateResponseWriter{}
DelKnownSession(csrw)
DelKnownCookie(csrw)
mustBeDel := func(ev ClientStateEvent) {
t.Helper()
if ev.Kind != ClientStateEventDel {
t.Error("events should all be deletes")
}
}
if len(csrw.sessionStateEvents) != 3 {
t.Error("should have deleted 3 session entries")
}
mustBeDel(csrw.sessionStateEvents[0])
mustBeDel(csrw.sessionStateEvents[1])
mustBeDel(csrw.sessionStateEvents[2])
for i, key := range []string{SessionKey, SessionHalfAuthKey, SessionLastAction} {
if sessionKey := csrw.sessionStateEvents[i].Key; key != sessionKey {
t.Errorf("%d) key was wrong, want: %s, got: %s", i, key, sessionKey)
}
}
if len(csrw.cookieStateEvents) != 1 {
t.Error("should have deleted 1 cookie")
}
mustBeDel(csrw.cookieStateEvents[0])
if key := csrw.cookieStateEvents[0].Key; key != CookieRemember {
t.Error("cookie key was wrong:", key)
}
}

39
defaults/defaults_test.go Normal file
View File

@ -0,0 +1,39 @@
package defaults
import (
"testing"
"github.com/volatiletech/authboss"
)
func TestSetCore(t *testing.T) {
t.Parallel()
config := &authboss.Config{}
SetCore(config, false, false)
if config.Core.Logger == nil {
t.Error("logger should be set")
}
if config.Core.Router == nil {
t.Error("router should be set")
}
if config.Core.ErrorHandler == nil {
t.Error("error handler should be set")
}
if config.Core.Responder == nil {
t.Error("responder should be set")
}
if config.Core.Redirector == nil {
t.Error("redirector should be set")
}
if config.Core.BodyReader == nil {
t.Error("bodyreader should be set")
}
if config.Core.Mailer == nil {
t.Error("mailer should be set")
}
if config.Core.Logger == nil {
t.Error("logger should be set")
}
}

View File

@ -9,7 +9,7 @@ import (
"github.com/volatiletech/authboss/internal/mocks"
)
func TestHTTPBodyReader(t *testing.T) {
func TestHTTPBodyReaderLogin(t *testing.T) {
t.Parallel()
h := NewHTTPBodyReader(false, false)
@ -48,3 +48,101 @@ func TestHTTPBodyReaderJSON(t *testing.T) {
t.Error("wrong password:", uv.GetPassword())
}
}
func TestHTTPBodyReaderConfirm(t *testing.T) {
t.Parallel()
h := NewHTTPBodyReader(false, false)
r := mocks.Request("POST", FormValueConfirm, "token")
validator, err := h.Read("confirm", r)
if err != nil {
t.Error(err)
}
cv := validator.(authboss.ConfirmValuer)
if "token" != cv.GetToken() {
t.Error("token was wrong:", cv.GetToken())
}
}
func TestHTTPBodyReaderRecoverStart(t *testing.T) {
t.Parallel()
h := NewHTTPBodyReader(false, false)
r := mocks.Request("POST", FormValueEmail, "email")
validator, err := h.Read("recover_start", r)
if err != nil {
t.Error(err)
}
rsv := validator.(authboss.RecoverStartValuer)
if pid := rsv.GetPID(); pid != "email" {
t.Error("token was wrong:", pid)
}
}
func TestHTTPBodyReaderRecoverMiddle(t *testing.T) {
t.Parallel()
h := NewHTTPBodyReader(false, false)
r := httptest.NewRequest("GET", "/?token=token", nil)
validator, err := h.Read("recover_middle", r)
if err != nil {
t.Error(err)
}
rmv := validator.(authboss.RecoverMiddleValuer)
if token := rmv.GetToken(); token != "token" {
t.Error("token was wrong:", token)
}
}
func TestHTTPBodyReaderRecoverEnd(t *testing.T) {
t.Parallel()
h := NewHTTPBodyReader(false, false)
r := mocks.Request("POST", "token", "token", "password", "password")
validator, err := h.Read("recover_end", r)
if err != nil {
t.Error(err)
}
rmv := validator.(authboss.RecoverEndValuer)
if token := rmv.GetToken(); token != "token" {
t.Error("token was wrong:", token)
}
if password := rmv.GetPassword(); password != "password" {
t.Error("password was wrong:", password)
}
}
func TestHTTPBodyReaderRegister(t *testing.T) {
t.Parallel()
h := NewHTTPBodyReader(false, false)
h.Whitelist["register"] = []string{"address"}
r := mocks.Request("POST", "email", "a@a.com", "password", "1234", "address", "555 go street")
validator, err := h.Read("register", r)
if err != nil {
t.Error(err)
}
rv := validator.(authboss.UserValuer)
if pid := rv.GetPID(); pid != "a@a.com" {
t.Error("pid was wrong:", pid)
}
if password := rv.GetPassword(); password != "1234" {
t.Error("password was wrong:", password)
}
arb := validator.(authboss.ArbitraryValuer)
values := arb.GetValues()
if address := values["address"]; address != "555 go street" {
t.Error("address was wrong:", address)
}
}

View File

@ -36,111 +36,111 @@ type User struct {
}
// GetPID from user
func (m User) GetPID() string { return m.Email }
func (u User) GetPID() string { return u.Email }
// GetEmail from user
func (m User) GetEmail() string { return m.Email }
func (u User) GetEmail() string { return u.Email }
// GetUsername from user
func (m User) GetUsername() string { return m.Username }
func (u User) GetUsername() string { return u.Username }
// GetPassword from user
func (m User) GetPassword() string { return m.Password }
func (u User) GetPassword() string { return u.Password }
// GetRecoverToken from user
func (m User) GetRecoverToken() string { return m.RecoverToken }
func (u User) GetRecoverToken() string { return u.RecoverToken }
// GetRecoverExpiry from user
func (m User) GetRecoverExpiry() time.Time { return m.RecoverTokenExpiry }
func (u User) GetRecoverExpiry() time.Time { return u.RecoverTokenExpiry }
// GetConfirmToken from user
func (m User) GetConfirmToken() string { return m.ConfirmToken }
func (u User) GetConfirmToken() string { return u.ConfirmToken }
// GetConfirmed from user
func (m User) GetConfirmed() bool { return m.Confirmed }
func (u User) GetConfirmed() bool { return u.Confirmed }
// GetAttemptCount from user
func (m User) GetAttemptCount() int { return m.AttemptCount }
func (u User) GetAttemptCount() int { return u.AttemptCount }
// GetLastAttempt from user
func (m User) GetLastAttempt() time.Time { return m.LastAttempt }
func (u User) GetLastAttempt() time.Time { return u.LastAttempt }
// GetLocked from user
func (m User) GetLocked() time.Time { return m.Locked }
func (u User) GetLocked() time.Time { return u.Locked }
// IsOAuth2User returns true if the user is an oauth2 user
func (m User) IsOAuth2User() bool { return len(m.OAuth2Provider) != 0 }
func (u User) IsOAuth2User() bool { return len(u.OAuth2Provider) != 0 }
// GetOAuth2UID from user
func (m User) GetOAuth2UID() string { return m.OAuth2UID }
func (u User) GetOAuth2UID() string { return u.OAuth2UID }
// GetOAuth2Provider from user
func (m User) GetOAuth2Provider() string { return m.OAuth2Provider }
func (u User) GetOAuth2Provider() string { return u.OAuth2Provider }
// GetOAuth2AccessToken from user
func (m User) GetOAuth2AccessToken() string { return m.OAuth2Token }
func (u User) GetOAuth2AccessToken() string { return u.OAuth2Token }
// GetOAuth2RefreshToken from user
func (m User) GetOAuth2RefreshToken() string { return m.OAuth2Refresh }
func (u User) GetOAuth2RefreshToken() string { return u.OAuth2Refresh }
// GetOAuth2Expiry from user
func (m User) GetOAuth2Expiry() time.Time { return m.OAuth2Expiry }
func (u User) GetOAuth2Expiry() time.Time { return u.OAuth2Expiry }
// GetArbitrary from user
func (m User) GetArbitrary() map[string]string { return m.Arbitrary }
func (u User) GetArbitrary() map[string]string { return u.Arbitrary }
// PutPID into user
func (m *User) PutPID(email string) { m.Email = email }
func (u *User) PutPID(email string) { u.Email = email }
// PutUsername into user
func (m *User) PutUsername(username string) { m.Username = username }
func (u *User) PutUsername(username string) { u.Username = username }
// PutEmail into user
func (m *User) PutEmail(email string) { m.Email = email }
func (u *User) PutEmail(email string) { u.Email = email }
// PutPassword into user
func (m *User) PutPassword(password string) { m.Password = password }
func (u *User) PutPassword(password string) { u.Password = password }
// PutRecoverToken into user
func (m *User) PutRecoverToken(recoverToken string) { m.RecoverToken = recoverToken }
func (u *User) PutRecoverToken(recoverToken string) { u.RecoverToken = recoverToken }
// PutRecoverExpiry into user
func (m *User) PutRecoverExpiry(recoverTokenExpiry time.Time) {
m.RecoverTokenExpiry = recoverTokenExpiry
func (u *User) PutRecoverExpiry(recoverTokenExpiry time.Time) {
u.RecoverTokenExpiry = recoverTokenExpiry
}
// PutConfirmToken into user
func (m *User) PutConfirmToken(confirmToken string) { m.ConfirmToken = confirmToken }
func (u *User) PutConfirmToken(confirmToken string) { u.ConfirmToken = confirmToken }
// PutConfirmed into user
func (m *User) PutConfirmed(confirmed bool) { m.Confirmed = confirmed }
func (u *User) PutConfirmed(confirmed bool) { u.Confirmed = confirmed }
// PutAttemptCount into user
func (m *User) PutAttemptCount(attemptCount int) { m.AttemptCount = attemptCount }
func (u *User) PutAttemptCount(attemptCount int) { u.AttemptCount = attemptCount }
// PutLastAttempt into user
func (m *User) PutLastAttempt(attemptTime time.Time) { m.LastAttempt = attemptTime }
func (u *User) PutLastAttempt(attemptTime time.Time) { u.LastAttempt = attemptTime }
// PutLocked into user
func (m *User) PutLocked(locked time.Time) { m.Locked = locked }
func (u *User) PutLocked(locked time.Time) { u.Locked = locked }
// PutOAuth2UID into user
func (m *User) PutOAuth2UID(uid string) { m.OAuth2UID = uid }
func (u *User) PutOAuth2UID(uid string) { u.OAuth2UID = uid }
// PutOAuth2Provider into user
func (m *User) PutOAuth2Provider(provider string) { m.OAuth2Provider = provider }
func (u *User) PutOAuth2Provider(provider string) { u.OAuth2Provider = provider }
// PutOAuth2AccessToken into user
func (m *User) PutOAuth2AccessToken(token string) { m.OAuth2Token = token }
func (u *User) PutOAuth2AccessToken(token string) { u.OAuth2Token = token }
// PutOAuth2RefreshToken into user
func (m *User) PutOAuth2RefreshToken(refresh string) { m.OAuth2Refresh = refresh }
func (u *User) PutOAuth2RefreshToken(refresh string) { u.OAuth2Refresh = refresh }
// PutOAuth2Expiry into user
func (m *User) PutOAuth2Expiry(expiry time.Time) { m.OAuth2Expiry = expiry }
func (u *User) PutOAuth2Expiry(expiry time.Time) { u.OAuth2Expiry = expiry }
// PutArbitrary into user
func (m *User) PutArbitrary(arb map[string]string) { m.Arbitrary = arb }
func (u *User) PutArbitrary(arb map[string]string) { u.Arbitrary = arb }
// ServerStorer should be valid for any module storer defined in authboss.
type ServerStorer struct {

View File

@ -31,6 +31,38 @@ func TestLogout(t *testing.T) {
}
}
func TestLogoutRoutes(t *testing.T) {
t.Parallel()
ab := authboss.New()
router := &mocks.Router{}
errHandler := &mocks.ErrorHandler{}
ab.Config.Core.Router = router
ab.Config.Core.ErrorHandler = errHandler
l := &Logout{}
ab.Config.Modules.LogoutMethod = "what"
if err := l.Init(ab); err == nil {
t.Error("should have failed to register the route")
}
ab.Config.Modules.LogoutMethod = "GET"
if err := l.Init(ab); err != nil {
t.Error("should have failed to register the route")
}
if err := router.HasGets("/logout"); err != nil {
t.Error(err)
}
ab.Config.Modules.LogoutMethod = "POST"
if err := l.Init(ab); err != nil {
t.Error("should have failed to register the route")
}
if err := router.HasPosts("/logout"); err != nil {
t.Error(err)
}
}
type testHarness struct {
logout *Logout
ab *authboss.Authboss

View File

@ -8,11 +8,31 @@ import (
"net/http"
"net/url"
"strings"
"time"
)
type mockUser struct {
Email string
Password string
Username string
RecoverToken string
RecoverTokenExpiry time.Time
ConfirmToken string
Confirmed bool
AttemptCount int
LastAttempt time.Time
Locked time.Time
OAuth2UID string
OAuth2Provider string
OAuth2Token string
OAuth2Refresh string
OAuth2Expiry time.Time
Arbitrary map[string]string
}
func newMockServerStorer() *mockServerStorer {
@ -70,21 +90,57 @@ func (m *mockServerStorer) UseRememberToken(pid, token string) error {
return ErrTokenNotFound
}
func (m *mockUser) PutPID(email string) {
m.Email = email
// This section of functions was purely for test coverage
func (m *mockServerStorer) New(ctx context.Context) User { panic("not impl") }
func (m *mockServerStorer) Create(ctx context.Context, user User) error { panic("not impl") }
func (m *mockServerStorer) NewFromOAuth2(ctx context.Context, provider string, details map[string]string) (OAuth2User, error) {
panic("not impl")
}
func (m *mockServerStorer) LoadByConfirmToken(ctx context.Context, token string) (ConfirmableUser, error) {
panic("not impl")
}
func (m *mockServerStorer) LoadByRecoverToken(ctx context.Context, token string) (RecoverableUser, error) {
panic("not impl")
}
func (m *mockServerStorer) SaveOAuth2(ctx context.Context, user OAuth2User) error { panic("not impl") }
func (m *mockUser) PutPassword(password string) {
m.Password = password
}
func (m *mockUser) GetPID() (email string) {
return m.Email
}
func (m *mockUser) GetPassword() (password string) {
return m.Password
func (m mockUser) GetPID() string { return m.Email }
func (m mockUser) GetEmail() string { return m.Email }
func (m mockUser) GetUsername() string { return m.Username }
func (m mockUser) GetPassword() string { return m.Password }
func (m mockUser) GetRecoverToken() string { return m.RecoverToken }
func (m mockUser) GetRecoverExpiry() time.Time { return m.RecoverTokenExpiry }
func (m mockUser) GetConfirmToken() string { return m.ConfirmToken }
func (m mockUser) GetConfirmed() bool { return m.Confirmed }
func (m mockUser) GetAttemptCount() int { return m.AttemptCount }
func (m mockUser) GetLastAttempt() time.Time { return m.LastAttempt }
func (m mockUser) GetLocked() time.Time { return m.Locked }
func (m mockUser) IsOAuth2User() bool { return len(m.OAuth2Provider) != 0 }
func (m mockUser) GetOAuth2UID() string { return m.OAuth2UID }
func (m mockUser) GetOAuth2Provider() string { return m.OAuth2Provider }
func (m mockUser) GetOAuth2AccessToken() string { return m.OAuth2Token }
func (m mockUser) GetOAuth2RefreshToken() string { return m.OAuth2Refresh }
func (m mockUser) GetOAuth2Expiry() time.Time { return m.OAuth2Expiry }
func (m mockUser) GetArbitrary() map[string]string { return m.Arbitrary }
func (m *mockUser) PutPID(email string) { m.Email = email }
func (m *mockUser) PutUsername(username string) { m.Username = username }
func (m *mockUser) PutEmail(email string) { m.Email = email }
func (m *mockUser) PutPassword(password string) { m.Password = password }
func (m *mockUser) PutRecoverToken(recoverToken string) { m.RecoverToken = recoverToken }
func (m *mockUser) PutRecoverExpiry(recoverTokenExpiry time.Time) {
m.RecoverTokenExpiry = recoverTokenExpiry
}
func (m *mockUser) PutConfirmToken(confirmToken string) { m.ConfirmToken = confirmToken }
func (m *mockUser) PutConfirmed(confirmed bool) { m.Confirmed = confirmed }
func (m *mockUser) PutAttemptCount(attemptCount int) { m.AttemptCount = attemptCount }
func (m *mockUser) PutLastAttempt(attemptTime time.Time) { m.LastAttempt = attemptTime }
func (m *mockUser) PutLocked(locked time.Time) { m.Locked = locked }
func (m *mockUser) PutOAuth2UID(uid string) { m.OAuth2UID = uid }
func (m *mockUser) PutOAuth2Provider(provider string) { m.OAuth2Provider = provider }
func (m *mockUser) PutOAuth2AccessToken(token string) { m.OAuth2Token = token }
func (m *mockUser) PutOAuth2RefreshToken(refresh string) { m.OAuth2Refresh = refresh }
func (m *mockUser) PutOAuth2Expiry(expiry time.Time) { m.OAuth2Expiry = expiry }
func (m *mockUser) PutArbitrary(arb map[string]string) { m.Arbitrary = arb }
type mockClientStateReadWriter struct {
state mockClientState
@ -178,9 +234,7 @@ type mockRenderer struct {
expectName string
}
func (m mockRenderer) Load(names ...string) error {
return nil
}
func (m mockRenderer) Load(names ...string) error { return nil }
func (m mockRenderer) Render(ctx context.Context, name string, data HTMLData) ([]byte, string, error) {
if len(m.expectName) != 0 && m.expectName != name {
@ -193,6 +247,8 @@ func (m mockRenderer) Render(ctx context.Context, name string, data HTMLData) ([
type mockEmailRenderer struct{}
func (m mockEmailRenderer) Load(names ...string) error { return nil }
func (m mockEmailRenderer) Render(ctx context.Context, name string, data HTMLData) ([]byte, string, error) {
switch name {
case "text":

43
response_test.go Normal file
View File

@ -0,0 +1,43 @@
package authboss
import (
"context"
"testing"
)
type testMailer struct{ sent bool }
func (t *testMailer) Send(context.Context, Email) error {
t.sent = true
return nil
}
func TestEmail(t *testing.T) {
t.Parallel()
ab := New()
mailer := &testMailer{}
renderer := &mockEmailRenderer{}
ab.Config.Core.Mailer = mailer
ab.Config.Core.MailRenderer = renderer
email := Email{
To: []string{"support@authboss.com"},
Subject: "Send help",
}
ro := EmailResponseOptions{
Data: nil,
HTMLTemplate: "html",
TextTemplate: "text",
}
if err := ab.Email(context.Background(), email, ro); err != nil {
t.Error(err)
}
if !mailer.sent {
t.Error("the e-mail should have been sent")
}
}

64
storage_test.go Normal file
View File

@ -0,0 +1,64 @@
package authboss
import (
"context"
"testing"
)
type testAssertionFailStorer struct{}
func (testAssertionFailStorer) Load(ctx context.Context, key string) (User, error) { return nil, nil }
func (testAssertionFailStorer) Save(ctx context.Context, user User) error { return nil }
func TestStorageAssertions(t *testing.T) {
t.Parallel()
s := &mockServerStorer{}
fs := testAssertionFailStorer{}
paniced := false
func() {
defer func() {
if r := recover(); r != nil {
paniced = true
}
}()
EnsureCanCreate(s)
EnsureCanConfirm(s)
EnsureCanRecover(s)
EnsureCanRemember(s)
EnsureCanOAuth2(s)
}()
if paniced {
t.Error("The mock storer should have included all interfaces and should not panic")
}
didPanic := func(f func()) (paniced bool) {
defer func() {
if r := recover(); r != nil {
paniced = true
}
}()
f()
return paniced
}
if !didPanic(func() { EnsureCanCreate(fs) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { EnsureCanConfirm(fs) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { EnsureCanRecover(fs) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { EnsureCanRemember(fs) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { EnsureCanOAuth2(fs) }) {
t.Error("should have panic'd")
}
}

View File

@ -51,3 +51,61 @@ func TestOAuth2PIDs(t *testing.T) {
t.Error("expected a panic when the pid doesn't start with oauth2")
}
}
type testAssertionFailUser struct{}
func (testAssertionFailUser) GetPID() string { return "" }
func (testAssertionFailUser) PutPID(string) {}
func TestUserAssertions(t *testing.T) {
t.Parallel()
u := &mockUser{}
fu := testAssertionFailUser{}
paniced := false
func() {
defer func() {
if r := recover(); r != nil {
paniced = true
}
}()
MustBeAuthable(u)
MustBeConfirmable(u)
MustBeLockable(u)
MustBeOAuthable(u)
MustBeRecoverable(u)
}()
if paniced {
t.Error("The mock user should have included all interfaces and should not panic")
}
didPanic := func(f func()) (paniced bool) {
defer func() {
if r := recover(); r != nil {
paniced = true
}
}()
f()
return paniced
}
if !didPanic(func() { MustBeAuthable(fu) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { MustBeConfirmable(fu) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { MustBeLockable(fu) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { MustBeOAuthable(fu) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { MustBeRecoverable(fu) }) {
t.Error("should have panic'd")
}
}

70
values_test.go Normal file
View File

@ -0,0 +1,70 @@
package authboss
import "testing"
type testAssertionValues struct{}
func (testAssertionValues) Validate() []error { return nil }
func (testAssertionValues) GetPID() string { return "" }
func (testAssertionValues) GetPassword() string { return "" }
func (testAssertionValues) GetToken() string { return "" }
func (testAssertionValues) GetShouldRemember() bool { return false }
func (testAssertionValues) GetValues() map[string]string { return nil }
type testAssertionFailValues struct{}
func (testAssertionFailValues) Validate() []error { return nil }
func TestValueAssertions(t *testing.T) {
t.Parallel()
v := testAssertionValues{}
fv := testAssertionFailValues{}
paniced := false
func() {
defer func() {
if r := recover(); r != nil {
paniced = true
}
}()
MustHaveUserValues(v)
MustHaveConfirmValues(v)
MustHaveRecoverStartValues(v)
MustHaveRecoverMiddleValues(v)
MustHaveRecoverEndValues(v)
}()
if paniced {
t.Error("The mock storer should have included all interfaces and should not panic")
}
didPanic := func(f func()) (paniced bool) {
defer func() {
if r := recover(); r != nil {
paniced = true
}
}()
f()
return paniced
}
if !didPanic(func() { MustHaveUserValues(fv) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { MustHaveConfirmValues(fv) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { MustHaveRecoverStartValues(fv) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { MustHaveRecoverMiddleValues(fv) }) {
t.Error("should have panic'd")
}
if !didPanic(func() { MustHaveRecoverEndValues(fv) }) {
t.Error("should have panic'd")
}
}