auth

Paddy 2014-09-18 Parent:1f7b44b130a0 Child:3a6a65ed380c

41:113ccb15b919 Go to Latest

auth/profile_test.go

Added validation for clients, split endpoints out. Split endpoints out into their own type and added associated methods to the ClientStores, so now each client can have more than one redirect endpoint. Added unit testing for endpoint methods. Added validation code to validate client changes.

History
paddy@38 1 package auth
paddy@38 2
paddy@38 3 import (
paddy@38 4 "fmt"
paddy@38 5 "testing"
paddy@38 6 "time"
paddy@38 7
paddy@38 8 "secondbit.org/uuid"
paddy@38 9 )
paddy@38 10
paddy@38 11 const (
paddy@38 12 profileChangeName = 1 << iota
paddy@38 13 profileChangePassphrase
paddy@38 14 profileChangeIterations
paddy@38 15 profileChangeSalt
paddy@38 16 profileChangePassphraseScheme
paddy@38 17 profileChangeCompromised
paddy@38 18 profileChangeLockedUntil
paddy@38 19 profileChangePassphraseReset
paddy@38 20 profileChangePassphraseResetCreated
paddy@38 21 profileChangeLastSeen
paddy@38 22 )
paddy@38 23
paddy@38 24 var profileStores = []ProfileStore{NewMemstore()}
paddy@38 25
paddy@38 26 func compareProfiles(profile1, profile2 Profile) (success bool, field string, val1, val2 interface{}) {
paddy@38 27 if !profile1.ID.Equal(profile2.ID) {
paddy@38 28 return false, "ID", profile1.ID, profile2.ID
paddy@38 29 }
paddy@38 30 if profile1.Name != profile2.Name {
paddy@38 31 return false, "name", profile1.Name, profile2.Name
paddy@38 32 }
paddy@38 33 if profile1.Passphrase != profile2.Passphrase {
paddy@38 34 return false, "passphrase", profile1.Passphrase, profile2.Passphrase
paddy@38 35 }
paddy@38 36 if profile1.Iterations != profile2.Iterations {
paddy@38 37 return false, "iterations", profile1.Iterations, profile2.Iterations
paddy@38 38 }
paddy@38 39 if profile1.Salt != profile2.Salt {
paddy@38 40 return false, "salt", profile1.Salt, profile2.Salt
paddy@38 41 }
paddy@38 42 if profile1.PassphraseScheme != profile2.PassphraseScheme {
paddy@38 43 return false, "passphrase scheme", profile1.PassphraseScheme, profile2.PassphraseScheme
paddy@38 44 }
paddy@38 45 if profile1.Compromised != profile2.Compromised {
paddy@38 46 return false, "compromised", profile1.Compromised, profile2.Compromised
paddy@38 47 }
paddy@38 48 if !profile1.LockedUntil.Equal(profile2.LockedUntil) {
paddy@38 49 return false, "locked until", profile1.LockedUntil, profile2.LockedUntil
paddy@38 50 }
paddy@38 51 if profile1.PassphraseReset != profile2.PassphraseReset {
paddy@38 52 return false, "passphrase reset", profile1.PassphraseReset, profile2.PassphraseReset
paddy@38 53 }
paddy@38 54 if !profile1.PassphraseResetCreated.Equal(profile2.PassphraseResetCreated) {
paddy@38 55 return false, "passphrase reset created", profile1.PassphraseResetCreated, profile2.PassphraseResetCreated
paddy@38 56 }
paddy@38 57 if !profile1.Created.Equal(profile2.Created) {
paddy@38 58 return false, "created", profile1.Created, profile2.Created
paddy@38 59 }
paddy@38 60 if !profile1.LastSeen.Equal(profile2.LastSeen) {
paddy@38 61 return false, "last seen", profile1.LastSeen, profile2.LastSeen
paddy@38 62 }
paddy@38 63 return true, "", nil, nil
paddy@38 64 }
paddy@38 65
paddy@38 66 func TestProfileStoreSuccess(t *testing.T) {
paddy@38 67 t.Parallel()
paddy@38 68 profile := Profile{
paddy@38 69 ID: uuid.NewID(),
paddy@38 70 Name: "name",
paddy@38 71 Passphrase: "passphrase",
paddy@38 72 Iterations: 10000,
paddy@38 73 Salt: "salt",
paddy@38 74 PassphraseScheme: 1,
paddy@38 75 Compromised: false,
paddy@38 76 LockedUntil: time.Now().Add(time.Hour),
paddy@38 77 PassphraseReset: "passphrase reset",
paddy@38 78 PassphraseResetCreated: time.Now(),
paddy@38 79 Created: time.Now(),
paddy@38 80 LastSeen: time.Now(),
paddy@38 81 }
paddy@38 82 for _, store := range profileStores {
paddy@38 83 err := store.SaveProfile(profile)
paddy@38 84 if err != nil {
paddy@38 85 t.Errorf("Error saving profile to %T: %s", store, err)
paddy@38 86 }
paddy@38 87 err = store.SaveProfile(profile)
paddy@38 88 if err != ErrProfileAlreadyExists {
paddy@38 89 t.Errorf("Expected ErrProfileAlreadyExists from %T, got %+v", store, err)
paddy@38 90 }
paddy@38 91 retrieved, err := store.GetProfileByID(profile.ID)
paddy@38 92 if err != nil {
paddy@38 93 t.Errorf("Error retrieving profile from %T: %s", store, err)
paddy@38 94 }
paddy@38 95 match, field, expectation, result := compareProfiles(profile, retrieved)
paddy@38 96 if !match {
paddy@38 97 t.Errorf("Expected `%v` in the `%s` field of profile retrieved from %T, got `%v`", expectation, field, store, result)
paddy@38 98 }
paddy@38 99 err = store.DeleteProfile(profile.ID)
paddy@38 100 if err != nil {
paddy@38 101 t.Errorf("Error removing profile from %T: %s", store, err)
paddy@38 102 }
paddy@38 103 retrieved, err = store.GetProfileByID(profile.ID)
paddy@38 104 if err != ErrProfileNotFound {
paddy@38 105 t.Errorf("Expected ErrProfileNotFound from %T, got %+v and %+v", store, retrieved, err)
paddy@38 106 }
paddy@38 107 err = store.DeleteProfile(profile.ID)
paddy@38 108 if err != ErrProfileNotFound {
paddy@38 109 t.Errorf("Expected ErrProfileNotFound from %T, got %+v", store, err)
paddy@38 110 }
paddy@38 111 }
paddy@38 112 }
paddy@38 113
paddy@38 114 func TestProfileUpdates(t *testing.T) {
paddy@38 115 t.Parallel()
paddy@38 116 variations := 1 << 10
paddy@38 117 profile := Profile{
paddy@38 118 ID: uuid.NewID(),
paddy@38 119 Name: "name",
paddy@38 120 Passphrase: "passphrase",
paddy@38 121 Iterations: 10000,
paddy@38 122 Salt: "salt",
paddy@38 123 PassphraseScheme: 1,
paddy@38 124 Compromised: false,
paddy@38 125 LockedUntil: time.Now().Add(time.Hour),
paddy@38 126 PassphraseReset: "passphrase reset",
paddy@38 127 PassphraseResetCreated: time.Now(),
paddy@38 128 Created: time.Now(),
paddy@38 129 LastSeen: time.Now(),
paddy@38 130 }
paddy@38 131 for i := 0; i < variations; i++ {
paddy@38 132 var name, passphrase, salt, passphraseReset string
paddy@38 133 var iterations int64
paddy@38 134 var lockedUntil, passphraseResetCreated, lastSeen time.Time
paddy@38 135 var passphraseScheme int
paddy@38 136 var compromised bool
paddy@38 137
paddy@38 138 change := ProfileChange{}
paddy@38 139 expectation := profile
paddy@38 140 result := profile
paddy@38 141 if i&profileChangeName != 0 {
paddy@38 142 name = fmt.Sprintf("name-%d", i)
paddy@38 143 change.Name = &name
paddy@38 144 expectation.Name = name
paddy@38 145 }
paddy@38 146 if i&profileChangePassphrase != 0 {
paddy@38 147 passphrase = fmt.Sprintf("passphrase-%d", i)
paddy@38 148 change.Passphrase = &passphrase
paddy@38 149 expectation.Passphrase = passphrase
paddy@38 150 }
paddy@38 151 if i&profileChangeIterations != 0 {
paddy@38 152 iterations = int64(i)
paddy@38 153 change.Iterations = &iterations
paddy@38 154 expectation.Iterations = iterations
paddy@38 155 }
paddy@38 156 if i&profileChangeSalt != 0 {
paddy@38 157 salt = fmt.Sprintf("salt-%d", i)
paddy@38 158 change.Salt = &salt
paddy@38 159 expectation.Salt = salt
paddy@38 160 }
paddy@38 161 if i&profileChangePassphraseScheme != 0 {
paddy@38 162 passphraseScheme = i
paddy@38 163 change.PassphraseScheme = &passphraseScheme
paddy@38 164 expectation.PassphraseScheme = passphraseScheme
paddy@38 165 }
paddy@38 166 if i&profileChangeCompromised != 0 {
paddy@38 167 compromised = i%2 != 0
paddy@38 168 change.Compromised = &compromised
paddy@38 169 expectation.Compromised = compromised
paddy@38 170 }
paddy@38 171 if i&profileChangeLockedUntil != 0 {
paddy@38 172 lockedUntil = time.Now()
paddy@38 173 change.LockedUntil = &lockedUntil
paddy@38 174 expectation.LockedUntil = lockedUntil
paddy@38 175 }
paddy@38 176 if i&profileChangePassphraseReset != 0 {
paddy@38 177 passphraseReset = fmt.Sprintf("passphraseReset-%d", i)
paddy@38 178 change.PassphraseReset = &passphraseReset
paddy@38 179 expectation.PassphraseReset = passphraseReset
paddy@38 180 }
paddy@38 181 if i&profileChangePassphraseResetCreated != 0 {
paddy@38 182 passphraseResetCreated = time.Now()
paddy@38 183 change.PassphraseResetCreated = &passphraseResetCreated
paddy@38 184 expectation.PassphraseResetCreated = passphraseResetCreated
paddy@38 185 }
paddy@38 186 if i&profileChangeLastSeen != 0 {
paddy@38 187 lastSeen = time.Now()
paddy@38 188 change.LastSeen = &lastSeen
paddy@38 189 expectation.LastSeen = lastSeen
paddy@38 190 }
paddy@38 191 result.ApplyChange(change)
paddy@38 192 match, field, expected, got := compareProfiles(expectation, result)
paddy@38 193 if !match {
paddy@38 194 t.Errorf("Expected field `%s` to be `%v`, got `%v`", field, expected, got)
paddy@38 195 }
paddy@38 196 for _, store := range profileStores {
paddy@38 197 err := store.SaveProfile(profile)
paddy@38 198 if err != nil {
paddy@38 199 t.Errorf("Error saving profile in %T: %s", store, err)
paddy@38 200 }
paddy@38 201 err = store.UpdateProfile(profile.ID, change)
paddy@38 202 if err != nil {
paddy@38 203 t.Errorf("Error updating profile in %T: %s", store, err)
paddy@38 204 }
paddy@38 205 retrieved, err := store.GetProfileByID(profile.ID)
paddy@38 206 if err != nil {
paddy@38 207 t.Errorf("Error getting profile from %T: %s", store, err)
paddy@38 208 }
paddy@38 209 match, field, expected, got = compareProfiles(expectation, retrieved)
paddy@38 210 if !match {
paddy@38 211 t.Errorf("Expected field `%s` to be `%v`, got `%v` from %T", field, expected, got, store)
paddy@38 212 }
paddy@38 213 err = store.DeleteProfile(profile.ID)
paddy@38 214 if err != nil {
paddy@38 215 t.Errorf("Error deleting profile from %T: %s", store, err)
paddy@38 216 }
paddy@38 217 err = store.UpdateProfile(profile.ID, change)
paddy@38 218 if err != ErrProfileNotFound {
paddy@38 219 t.Errorf("Expected ErrProfileNotFound, got %v from %T", err, store)
paddy@38 220 }
paddy@38 221 }
paddy@38 222 }
paddy@38 223 }