auth
2014-09-07
Child:3a6a65ed380c
auth/profile_test.go
Update profiles and add tests. Add tests for profile storage. Make Memstore implement the profilestore interface. Get the groundwork of profiles laid.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/profile_test.go Sun Sep 07 19:09:01 2014 -0400 1.3 @@ -0,0 +1,223 @@ 1.4 +package auth 1.5 + 1.6 +import ( 1.7 + "fmt" 1.8 + "testing" 1.9 + "time" 1.10 + 1.11 + "secondbit.org/uuid" 1.12 +) 1.13 + 1.14 +const ( 1.15 + profileChangeName = 1 << iota 1.16 + profileChangePassphrase 1.17 + profileChangeIterations 1.18 + profileChangeSalt 1.19 + profileChangePassphraseScheme 1.20 + profileChangeCompromised 1.21 + profileChangeLockedUntil 1.22 + profileChangePassphraseReset 1.23 + profileChangePassphraseResetCreated 1.24 + profileChangeLastSeen 1.25 +) 1.26 + 1.27 +var profileStores = []ProfileStore{NewMemstore()} 1.28 + 1.29 +func compareProfiles(profile1, profile2 Profile) (success bool, field string, val1, val2 interface{}) { 1.30 + if !profile1.ID.Equal(profile2.ID) { 1.31 + return false, "ID", profile1.ID, profile2.ID 1.32 + } 1.33 + if profile1.Name != profile2.Name { 1.34 + return false, "name", profile1.Name, profile2.Name 1.35 + } 1.36 + if profile1.Passphrase != profile2.Passphrase { 1.37 + return false, "passphrase", profile1.Passphrase, profile2.Passphrase 1.38 + } 1.39 + if profile1.Iterations != profile2.Iterations { 1.40 + return false, "iterations", profile1.Iterations, profile2.Iterations 1.41 + } 1.42 + if profile1.Salt != profile2.Salt { 1.43 + return false, "salt", profile1.Salt, profile2.Salt 1.44 + } 1.45 + if profile1.PassphraseScheme != profile2.PassphraseScheme { 1.46 + return false, "passphrase scheme", profile1.PassphraseScheme, profile2.PassphraseScheme 1.47 + } 1.48 + if profile1.Compromised != profile2.Compromised { 1.49 + return false, "compromised", profile1.Compromised, profile2.Compromised 1.50 + } 1.51 + if !profile1.LockedUntil.Equal(profile2.LockedUntil) { 1.52 + return false, "locked until", profile1.LockedUntil, profile2.LockedUntil 1.53 + } 1.54 + if profile1.PassphraseReset != profile2.PassphraseReset { 1.55 + return false, "passphrase reset", profile1.PassphraseReset, profile2.PassphraseReset 1.56 + } 1.57 + if !profile1.PassphraseResetCreated.Equal(profile2.PassphraseResetCreated) { 1.58 + return false, "passphrase reset created", profile1.PassphraseResetCreated, profile2.PassphraseResetCreated 1.59 + } 1.60 + if !profile1.Created.Equal(profile2.Created) { 1.61 + return false, "created", profile1.Created, profile2.Created 1.62 + } 1.63 + if !profile1.LastSeen.Equal(profile2.LastSeen) { 1.64 + return false, "last seen", profile1.LastSeen, profile2.LastSeen 1.65 + } 1.66 + return true, "", nil, nil 1.67 +} 1.68 + 1.69 +func TestProfileStoreSuccess(t *testing.T) { 1.70 + t.Parallel() 1.71 + profile := Profile{ 1.72 + ID: uuid.NewID(), 1.73 + Name: "name", 1.74 + Passphrase: "passphrase", 1.75 + Iterations: 10000, 1.76 + Salt: "salt", 1.77 + PassphraseScheme: 1, 1.78 + Compromised: false, 1.79 + LockedUntil: time.Now().Add(time.Hour), 1.80 + PassphraseReset: "passphrase reset", 1.81 + PassphraseResetCreated: time.Now(), 1.82 + Created: time.Now(), 1.83 + LastSeen: time.Now(), 1.84 + } 1.85 + for _, store := range profileStores { 1.86 + err := store.SaveProfile(profile) 1.87 + if err != nil { 1.88 + t.Errorf("Error saving profile to %T: %s", store, err) 1.89 + } 1.90 + err = store.SaveProfile(profile) 1.91 + if err != ErrProfileAlreadyExists { 1.92 + t.Errorf("Expected ErrProfileAlreadyExists from %T, got %+v", store, err) 1.93 + } 1.94 + retrieved, err := store.GetProfileByID(profile.ID) 1.95 + if err != nil { 1.96 + t.Errorf("Error retrieving profile from %T: %s", store, err) 1.97 + } 1.98 + match, field, expectation, result := compareProfiles(profile, retrieved) 1.99 + if !match { 1.100 + t.Errorf("Expected `%v` in the `%s` field of profile retrieved from %T, got `%v`", expectation, field, store, result) 1.101 + } 1.102 + err = store.DeleteProfile(profile.ID) 1.103 + if err != nil { 1.104 + t.Errorf("Error removing profile from %T: %s", store, err) 1.105 + } 1.106 + retrieved, err = store.GetProfileByID(profile.ID) 1.107 + if err != ErrProfileNotFound { 1.108 + t.Errorf("Expected ErrProfileNotFound from %T, got %+v and %+v", store, retrieved, err) 1.109 + } 1.110 + err = store.DeleteProfile(profile.ID) 1.111 + if err != ErrProfileNotFound { 1.112 + t.Errorf("Expected ErrProfileNotFound from %T, got %+v", store, err) 1.113 + } 1.114 + } 1.115 +} 1.116 + 1.117 +func TestProfileUpdates(t *testing.T) { 1.118 + t.Parallel() 1.119 + variations := 1 << 10 1.120 + profile := Profile{ 1.121 + ID: uuid.NewID(), 1.122 + Name: "name", 1.123 + Passphrase: "passphrase", 1.124 + Iterations: 10000, 1.125 + Salt: "salt", 1.126 + PassphraseScheme: 1, 1.127 + Compromised: false, 1.128 + LockedUntil: time.Now().Add(time.Hour), 1.129 + PassphraseReset: "passphrase reset", 1.130 + PassphraseResetCreated: time.Now(), 1.131 + Created: time.Now(), 1.132 + LastSeen: time.Now(), 1.133 + } 1.134 + for i := 0; i < variations; i++ { 1.135 + var name, passphrase, salt, passphraseReset string 1.136 + var iterations int64 1.137 + var lockedUntil, passphraseResetCreated, lastSeen time.Time 1.138 + var passphraseScheme int 1.139 + var compromised bool 1.140 + 1.141 + change := ProfileChange{} 1.142 + expectation := profile 1.143 + result := profile 1.144 + if i&profileChangeName != 0 { 1.145 + name = fmt.Sprintf("name-%d", i) 1.146 + change.Name = &name 1.147 + expectation.Name = name 1.148 + } 1.149 + if i&profileChangePassphrase != 0 { 1.150 + passphrase = fmt.Sprintf("passphrase-%d", i) 1.151 + change.Passphrase = &passphrase 1.152 + expectation.Passphrase = passphrase 1.153 + } 1.154 + if i&profileChangeIterations != 0 { 1.155 + iterations = int64(i) 1.156 + change.Iterations = &iterations 1.157 + expectation.Iterations = iterations 1.158 + } 1.159 + if i&profileChangeSalt != 0 { 1.160 + salt = fmt.Sprintf("salt-%d", i) 1.161 + change.Salt = &salt 1.162 + expectation.Salt = salt 1.163 + } 1.164 + if i&profileChangePassphraseScheme != 0 { 1.165 + passphraseScheme = i 1.166 + change.PassphraseScheme = &passphraseScheme 1.167 + expectation.PassphraseScheme = passphraseScheme 1.168 + } 1.169 + if i&profileChangeCompromised != 0 { 1.170 + compromised = i%2 != 0 1.171 + change.Compromised = &compromised 1.172 + expectation.Compromised = compromised 1.173 + } 1.174 + if i&profileChangeLockedUntil != 0 { 1.175 + lockedUntil = time.Now() 1.176 + change.LockedUntil = &lockedUntil 1.177 + expectation.LockedUntil = lockedUntil 1.178 + } 1.179 + if i&profileChangePassphraseReset != 0 { 1.180 + passphraseReset = fmt.Sprintf("passphraseReset-%d", i) 1.181 + change.PassphraseReset = &passphraseReset 1.182 + expectation.PassphraseReset = passphraseReset 1.183 + } 1.184 + if i&profileChangePassphraseResetCreated != 0 { 1.185 + passphraseResetCreated = time.Now() 1.186 + change.PassphraseResetCreated = &passphraseResetCreated 1.187 + expectation.PassphraseResetCreated = passphraseResetCreated 1.188 + } 1.189 + if i&profileChangeLastSeen != 0 { 1.190 + lastSeen = time.Now() 1.191 + change.LastSeen = &lastSeen 1.192 + expectation.LastSeen = lastSeen 1.193 + } 1.194 + result.ApplyChange(change) 1.195 + match, field, expected, got := compareProfiles(expectation, result) 1.196 + if !match { 1.197 + t.Errorf("Expected field `%s` to be `%v`, got `%v`", field, expected, got) 1.198 + } 1.199 + for _, store := range profileStores { 1.200 + err := store.SaveProfile(profile) 1.201 + if err != nil { 1.202 + t.Errorf("Error saving profile in %T: %s", store, err) 1.203 + } 1.204 + err = store.UpdateProfile(profile.ID, change) 1.205 + if err != nil { 1.206 + t.Errorf("Error updating profile in %T: %s", store, err) 1.207 + } 1.208 + retrieved, err := store.GetProfileByID(profile.ID) 1.209 + if err != nil { 1.210 + t.Errorf("Error getting profile from %T: %s", store, err) 1.211 + } 1.212 + match, field, expected, got = compareProfiles(expectation, retrieved) 1.213 + if !match { 1.214 + t.Errorf("Expected field `%s` to be `%v`, got `%v` from %T", field, expected, got, store) 1.215 + } 1.216 + err = store.DeleteProfile(profile.ID) 1.217 + if err != nil { 1.218 + t.Errorf("Error deleting profile from %T: %s", store, err) 1.219 + } 1.220 + err = store.UpdateProfile(profile.ID, change) 1.221 + if err != ErrProfileNotFound { 1.222 + t.Errorf("Expected ErrProfileNotFound, got %v from %T", err, store) 1.223 + } 1.224 + } 1.225 + } 1.226 +}