auth
auth/token_test.go
Test our getClientAuth helper, switch to table-based tests. Our getClientAuth helper was being tested implicitly when we tested our verifyClient helper, but let's test them separately. While we're at it, let's use table based tests instead of copy and paste. I noticed a lot of copy/paste errors while I was updating this, and the less test code we have and the easier we make it to test new edge cases, the better of we are.
| paddy@28 | 1 package auth |
| paddy@28 | 2 |
| paddy@28 | 3 import ( |
| paddy@28 | 4 "testing" |
| paddy@28 | 5 "time" |
| paddy@28 | 6 |
| paddy@107 | 7 "code.secondbit.org/uuid.hg" |
| paddy@28 | 8 ) |
| paddy@28 | 9 |
| paddy@57 | 10 var tokenStores = []tokenStore{NewMemstore()} |
| paddy@28 | 11 |
| paddy@35 | 12 func compareTokens(token1, token2 Token) (success bool, field string, val1, val2 interface{}) { |
| paddy@35 | 13 if token1.AccessToken != token2.AccessToken { |
| paddy@35 | 14 return false, "access token", token1.AccessToken, token2.AccessToken |
| paddy@35 | 15 } |
| paddy@35 | 16 if token1.RefreshToken != token2.RefreshToken { |
| paddy@35 | 17 return false, "refresh token", token1.RefreshToken, token2.RefreshToken |
| paddy@35 | 18 } |
| paddy@35 | 19 if !token1.Created.Equal(token2.Created) { |
| paddy@35 | 20 return false, "created", token1.Created, token2.Created |
| paddy@35 | 21 } |
| paddy@97 | 22 if token1.CreatedFrom != token2.CreatedFrom { |
| paddy@97 | 23 return false, "created from", token1.CreatedFrom, token2.CreatedFrom |
| paddy@97 | 24 } |
| paddy@35 | 25 if token1.ExpiresIn != token2.ExpiresIn { |
| paddy@35 | 26 return false, "expires in", token1.ExpiresIn, token2.ExpiresIn |
| paddy@35 | 27 } |
| paddy@35 | 28 if token1.TokenType != token2.TokenType { |
| paddy@35 | 29 return false, "token type", token1.TokenType, token2.TokenType |
| paddy@35 | 30 } |
| paddy@35 | 31 if token1.Scope != token2.Scope { |
| paddy@35 | 32 return false, "scope", token1.Scope, token2.Scope |
| paddy@35 | 33 } |
| paddy@35 | 34 if !token1.ProfileID.Equal(token2.ProfileID) { |
| paddy@35 | 35 return false, "profile ID", token1.ProfileID, token2.ProfileID |
| paddy@35 | 36 } |
| paddy@97 | 37 if token1.Revoked != token2.Revoked { |
| paddy@97 | 38 return false, "revoked", token1.Revoked, token2.Revoked |
| paddy@97 | 39 } |
| paddy@35 | 40 return true, "", nil, nil |
| paddy@35 | 41 } |
| paddy@35 | 42 |
| paddy@28 | 43 func TestTokenStoreSuccess(t *testing.T) { |
| paddy@37 | 44 t.Parallel() |
| paddy@28 | 45 token := Token{ |
| paddy@28 | 46 AccessToken: "access", |
| paddy@28 | 47 RefreshToken: "refresh", |
| paddy@28 | 48 Created: time.Now(), |
| paddy@28 | 49 ExpiresIn: 3600, |
| paddy@28 | 50 TokenType: "bearer", |
| paddy@28 | 51 Scope: "scope", |
| paddy@28 | 52 ProfileID: uuid.NewID(), |
| paddy@28 | 53 } |
| paddy@35 | 54 for _, store := range tokenStores { |
| paddy@116 | 55 context := Context{tokens: store} |
| paddy@127 | 56 retrievedAccess, err := context.GetToken(token.AccessToken, false) |
| paddy@127 | 57 if err == nil { |
| paddy@127 | 58 t.Errorf("Expected ErrTokenNotFound from %T, got %+v", store, retrievedAccess) |
| paddy@127 | 59 } else if err != ErrTokenNotFound { |
| paddy@127 | 60 t.Errorf("Expected ErrTokenNotFound from %T, got %s", store, err) |
| paddy@127 | 61 } |
| paddy@127 | 62 retrievedRefresh, err := context.GetToken(token.RefreshToken, true) |
| paddy@127 | 63 if err == nil { |
| paddy@127 | 64 t.Errorf("Expected ErrTokenNotFound from %T, got %+v", store, retrievedRefresh) |
| paddy@127 | 65 } else if err != ErrTokenNotFound { |
| paddy@127 | 66 t.Errorf("Expected ErrTokenNotFound from %T, got %s", store, err) |
| paddy@127 | 67 } |
| paddy@127 | 68 err = context.RevokeToken(token.AccessToken, false) |
| paddy@127 | 69 if err != ErrTokenNotFound { |
| paddy@127 | 70 t.Errorf("Expected ErrTokenNotFound from %T, got %s", store, err) |
| paddy@127 | 71 } |
| paddy@127 | 72 err = context.RevokeToken(token.RefreshToken, true) |
| paddy@127 | 73 if err != ErrTokenNotFound { |
| paddy@127 | 74 t.Errorf("Expected ErrTokenNotFound from %T, got %s", store, err) |
| paddy@127 | 75 } |
| paddy@127 | 76 err = context.SaveToken(token) |
| paddy@28 | 77 if err != nil { |
| paddy@37 | 78 t.Errorf("Error saving token to %T: %s", store, err) |
| paddy@37 | 79 } |
| paddy@116 | 80 err = context.SaveToken(token) |
| paddy@37 | 81 if err != ErrTokenAlreadyExists { |
| paddy@37 | 82 t.Errorf("Expected ErrTokenAlreadyExists from %T, got %s", store, err) |
| paddy@28 | 83 } |
| paddy@127 | 84 retrievedAccess, err = context.GetToken(token.AccessToken, false) |
| paddy@28 | 85 if err != nil { |
| paddy@35 | 86 t.Errorf("Error retrieving token from %T: %s", store, err) |
| paddy@28 | 87 } |
| paddy@35 | 88 success, field, expectation, result := compareTokens(token, retrievedAccess) |
| paddy@35 | 89 if !success { |
| paddy@35 | 90 t.Errorf("Expected field %s to be %v, but got %v from %T", field, expectation, result, store) |
| paddy@35 | 91 } |
| paddy@127 | 92 retrievedRefresh, err = context.GetToken(token.RefreshToken, true) |
| paddy@28 | 93 if err != nil { |
| paddy@35 | 94 t.Errorf("Error retrieving refresh token from %T: %s", store, err) |
| paddy@28 | 95 } |
| paddy@35 | 96 success, field, expectation, result = compareTokens(token, retrievedRefresh) |
| paddy@35 | 97 if !success { |
| paddy@35 | 98 t.Errorf("Expected field %s to be %v, but got %v from %T", field, expectation, result, store) |
| paddy@35 | 99 } |
| paddy@116 | 100 retrievedProfile, err := context.GetTokensByProfileID(token.ProfileID, 25, 0) |
| paddy@28 | 101 if err != nil { |
| paddy@35 | 102 t.Errorf("Error retrieving token by profile from %T: %s", store, err) |
| paddy@28 | 103 } |
| paddy@28 | 104 if len(retrievedProfile) != 1 { |
| paddy@35 | 105 t.Errorf("Expected 1 token retrieved by profile ID from %T, got %+v", store, retrievedProfile) |
| paddy@28 | 106 } |
| paddy@35 | 107 success, field, expectation, result = compareTokens(token, retrievedProfile[0]) |
| paddy@35 | 108 if !success { |
| paddy@35 | 109 t.Errorf("Expected field %s to be %v, but got %v from %T", field, expectation, result, store) |
| paddy@35 | 110 } |
| paddy@116 | 111 err = context.RevokeToken(token.AccessToken, false) |
| paddy@97 | 112 if err != nil { |
| paddy@97 | 113 t.Errorf("Error revoking token in %T: %s", store, err) |
| paddy@97 | 114 } |
| paddy@116 | 115 retrievedRevoked, err := context.GetToken(token.AccessToken, false) |
| paddy@97 | 116 if err != nil { |
| paddy@97 | 117 t.Errorf("Error retrieving token from %T: %s", store, err) |
| paddy@97 | 118 } |
| paddy@97 | 119 token.Revoked = true |
| paddy@97 | 120 success, field, expectation, result = compareTokens(token, retrievedRevoked) |
| paddy@97 | 121 if !success { |
| paddy@97 | 122 t.Errorf("Expected field %s to be %v, but got %v from %T", field, expectation, result, store) |
| paddy@97 | 123 } |
| paddy@127 | 124 err = context.RevokeToken(token.RefreshToken, true) |
| paddy@28 | 125 if err != nil { |
| paddy@127 | 126 t.Errorf("Error revoking token in %T: %s", store, err) |
| paddy@28 | 127 } |
| paddy@127 | 128 retrievedRevoked, err = context.GetToken(token.RefreshToken, true) |
| paddy@127 | 129 if err != nil { |
| paddy@127 | 130 t.Errorf("Error retrieving token from %T: %s", store, err) |
| paddy@28 | 131 } |
| paddy@127 | 132 token.RefreshRevoked = true |
| paddy@127 | 133 success, field, expectation, result = compareTokens(token, retrievedRevoked) |
| paddy@127 | 134 if !success { |
| paddy@127 | 135 t.Errorf("Expected field %s to be %v, but got %v from %T", field, expectation, result, store) |
| paddy@97 | 136 } |
| paddy@28 | 137 } |
| paddy@28 | 138 } |
| paddy@128 | 139 |
| paddy@128 | 140 // BUG(paddy): We need to test the refreshTokenValidate function. |
| paddy@128 | 141 // BUG(paddy): We need to test the refreshTokenInvalidate function. |