auth

Paddy 2015-01-19 Parent:e000b1c24fc0 Child:b5432f50f057

128:23c1a07c8a61 Go to Latest

auth/profile_test.go

Add our BUG notices. Rather than keeping the list of things to implement or test on sticky notes attached to my monitor, let's give them BUG designations within the code. Now `godoc . bugs` will list them out for us. Isn't that nice?

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@107 8 "code.secondbit.org/uuid.hg"
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@57 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@46 66 func compareLogins(login1, login2 Login) (success bool, field string, val1, val2 interface{}) {
paddy@46 67 if login1.Type != login2.Type {
paddy@46 68 return false, "Type", login1.Type, login2.Type
paddy@46 69 }
paddy@46 70 if login1.Value != login2.Value {
paddy@46 71 return false, "Value", login1.Value, login2.Value
paddy@46 72 }
paddy@46 73 if !login1.ProfileID.Equal(login2.ProfileID) {
paddy@46 74 return false, "ProfileID", login1.ProfileID, login2.ProfileID
paddy@46 75 }
paddy@46 76 if !login1.Created.Equal(login2.Created) {
paddy@46 77 return false, "Created", login1.Created, login2.Created
paddy@46 78 }
paddy@46 79 if !login1.LastUsed.Equal(login2.LastUsed) {
paddy@46 80 return false, "LastUsed", login1.LastUsed, login2.LastUsed
paddy@46 81 }
paddy@46 82 return true, "", nil, nil
paddy@46 83 }
paddy@46 84
paddy@38 85 func TestProfileStoreSuccess(t *testing.T) {
paddy@38 86 t.Parallel()
paddy@38 87 profile := Profile{
paddy@38 88 ID: uuid.NewID(),
paddy@38 89 Name: "name",
paddy@38 90 Passphrase: "passphrase",
paddy@38 91 Iterations: 10000,
paddy@38 92 Salt: "salt",
paddy@38 93 PassphraseScheme: 1,
paddy@38 94 Compromised: false,
paddy@38 95 LockedUntil: time.Now().Add(time.Hour),
paddy@38 96 PassphraseReset: "passphrase reset",
paddy@38 97 PassphraseResetCreated: time.Now(),
paddy@38 98 Created: time.Now(),
paddy@38 99 LastSeen: time.Now(),
paddy@38 100 }
paddy@38 101 for _, store := range profileStores {
paddy@116 102 context := Context{profiles: store}
paddy@116 103 err := context.SaveProfile(profile)
paddy@38 104 if err != nil {
paddy@38 105 t.Errorf("Error saving profile to %T: %s", store, err)
paddy@38 106 }
paddy@116 107 err = context.SaveProfile(profile)
paddy@38 108 if err != ErrProfileAlreadyExists {
paddy@38 109 t.Errorf("Expected ErrProfileAlreadyExists from %T, got %+v", store, err)
paddy@38 110 }
paddy@116 111 retrieved, err := context.GetProfileByID(profile.ID)
paddy@38 112 if err != nil {
paddy@38 113 t.Errorf("Error retrieving profile from %T: %s", store, err)
paddy@38 114 }
paddy@38 115 match, field, expectation, result := compareProfiles(profile, retrieved)
paddy@38 116 if !match {
paddy@38 117 t.Errorf("Expected `%v` in the `%s` field of profile retrieved from %T, got `%v`", expectation, field, store, result)
paddy@38 118 }
paddy@116 119 err = context.DeleteProfile(profile.ID)
paddy@38 120 if err != nil {
paddy@38 121 t.Errorf("Error removing profile from %T: %s", store, err)
paddy@38 122 }
paddy@116 123 retrieved, err = context.GetProfileByID(profile.ID)
paddy@38 124 if err != ErrProfileNotFound {
paddy@38 125 t.Errorf("Expected ErrProfileNotFound from %T, got %+v and %+v", store, retrieved, err)
paddy@38 126 }
paddy@116 127 err = context.DeleteProfile(profile.ID)
paddy@38 128 if err != ErrProfileNotFound {
paddy@38 129 t.Errorf("Expected ErrProfileNotFound from %T, got %+v", store, err)
paddy@38 130 }
paddy@38 131 }
paddy@38 132 }
paddy@38 133
paddy@38 134 func TestProfileUpdates(t *testing.T) {
paddy@38 135 t.Parallel()
paddy@38 136 variations := 1 << 10
paddy@38 137 profile := Profile{
paddy@38 138 ID: uuid.NewID(),
paddy@38 139 Name: "name",
paddy@38 140 Passphrase: "passphrase",
paddy@38 141 Iterations: 10000,
paddy@38 142 Salt: "salt",
paddy@38 143 PassphraseScheme: 1,
paddy@38 144 Compromised: false,
paddy@38 145 LockedUntil: time.Now().Add(time.Hour),
paddy@38 146 PassphraseReset: "passphrase reset",
paddy@38 147 PassphraseResetCreated: time.Now(),
paddy@38 148 Created: time.Now(),
paddy@38 149 LastSeen: time.Now(),
paddy@38 150 }
paddy@38 151 for i := 0; i < variations; i++ {
paddy@38 152 var name, passphrase, salt, passphraseReset string
paddy@69 153 var iterations int
paddy@38 154 var lockedUntil, passphraseResetCreated, lastSeen time.Time
paddy@38 155 var passphraseScheme int
paddy@38 156 var compromised bool
paddy@38 157
paddy@38 158 change := ProfileChange{}
paddy@38 159 expectation := profile
paddy@38 160 result := profile
paddy@38 161 if i&profileChangeName != 0 {
paddy@38 162 name = fmt.Sprintf("name-%d", i)
paddy@38 163 change.Name = &name
paddy@38 164 expectation.Name = name
paddy@38 165 }
paddy@38 166 if i&profileChangePassphrase != 0 {
paddy@38 167 passphrase = fmt.Sprintf("passphrase-%d", i)
paddy@38 168 change.Passphrase = &passphrase
paddy@38 169 expectation.Passphrase = passphrase
paddy@38 170 }
paddy@38 171 if i&profileChangeIterations != 0 {
paddy@69 172 iterations = i
paddy@38 173 change.Iterations = &iterations
paddy@38 174 expectation.Iterations = iterations
paddy@38 175 }
paddy@38 176 if i&profileChangeSalt != 0 {
paddy@38 177 salt = fmt.Sprintf("salt-%d", i)
paddy@38 178 change.Salt = &salt
paddy@38 179 expectation.Salt = salt
paddy@38 180 }
paddy@38 181 if i&profileChangePassphraseScheme != 0 {
paddy@38 182 passphraseScheme = i
paddy@38 183 change.PassphraseScheme = &passphraseScheme
paddy@38 184 expectation.PassphraseScheme = passphraseScheme
paddy@38 185 }
paddy@38 186 if i&profileChangeCompromised != 0 {
paddy@38 187 compromised = i%2 != 0
paddy@38 188 change.Compromised = &compromised
paddy@38 189 expectation.Compromised = compromised
paddy@38 190 }
paddy@38 191 if i&profileChangeLockedUntil != 0 {
paddy@38 192 lockedUntil = time.Now()
paddy@38 193 change.LockedUntil = &lockedUntil
paddy@38 194 expectation.LockedUntil = lockedUntil
paddy@38 195 }
paddy@38 196 if i&profileChangePassphraseReset != 0 {
paddy@38 197 passphraseReset = fmt.Sprintf("passphraseReset-%d", i)
paddy@38 198 change.PassphraseReset = &passphraseReset
paddy@38 199 expectation.PassphraseReset = passphraseReset
paddy@38 200 }
paddy@38 201 if i&profileChangePassphraseResetCreated != 0 {
paddy@38 202 passphraseResetCreated = time.Now()
paddy@38 203 change.PassphraseResetCreated = &passphraseResetCreated
paddy@38 204 expectation.PassphraseResetCreated = passphraseResetCreated
paddy@38 205 }
paddy@38 206 if i&profileChangeLastSeen != 0 {
paddy@38 207 lastSeen = time.Now()
paddy@38 208 change.LastSeen = &lastSeen
paddy@38 209 expectation.LastSeen = lastSeen
paddy@38 210 }
paddy@38 211 result.ApplyChange(change)
paddy@38 212 match, field, expected, got := compareProfiles(expectation, result)
paddy@38 213 if !match {
paddy@38 214 t.Errorf("Expected field `%s` to be `%v`, got `%v`", field, expected, got)
paddy@38 215 }
paddy@38 216 for _, store := range profileStores {
paddy@116 217 context := Context{profiles: store}
paddy@116 218 err := context.SaveProfile(profile)
paddy@38 219 if err != nil {
paddy@38 220 t.Errorf("Error saving profile in %T: %s", store, err)
paddy@38 221 }
paddy@116 222 err = context.UpdateProfile(profile.ID, change)
paddy@38 223 if err != nil {
paddy@38 224 t.Errorf("Error updating profile in %T: %s", store, err)
paddy@38 225 }
paddy@116 226 retrieved, err := context.GetProfileByID(profile.ID)
paddy@38 227 if err != nil {
paddy@38 228 t.Errorf("Error getting profile from %T: %s", store, err)
paddy@38 229 }
paddy@38 230 match, field, expected, got = compareProfiles(expectation, retrieved)
paddy@38 231 if !match {
paddy@38 232 t.Errorf("Expected field `%s` to be `%v`, got `%v` from %T", field, expected, got, store)
paddy@38 233 }
paddy@116 234 err = context.DeleteProfile(profile.ID)
paddy@38 235 if err != nil {
paddy@38 236 t.Errorf("Error deleting profile from %T: %s", store, err)
paddy@38 237 }
paddy@116 238 err = context.UpdateProfile(profile.ID, change)
paddy@38 239 if err != ErrProfileNotFound {
paddy@38 240 t.Errorf("Expected ErrProfileNotFound, got %v from %T", err, store)
paddy@38 241 }
paddy@38 242 }
paddy@38 243 }
paddy@38 244 }
paddy@45 245
paddy@45 246 func TestProfilesUpdates(t *testing.T) {
paddy@45 247 profile1 := Profile{
paddy@45 248 ID: uuid.NewID(),
paddy@45 249 }
paddy@45 250 profile2 := Profile{
paddy@45 251 ID: uuid.NewID(),
paddy@45 252 }
paddy@45 253 profile3 := Profile{
paddy@45 254 ID: uuid.NewID(),
paddy@45 255 }
paddy@45 256 truth := true
paddy@45 257 change := BulkProfileChange{
paddy@45 258 Compromised: &truth,
paddy@45 259 }
paddy@45 260 for _, store := range profileStores {
paddy@116 261 context := Context{profiles: store}
paddy@116 262 err := context.SaveProfile(profile1)
paddy@45 263 if err != nil {
paddy@45 264 t.Errorf("Error saving profile in %T: %s", store, err)
paddy@45 265 }
paddy@116 266 err = context.SaveProfile(profile2)
paddy@45 267 if err != nil {
paddy@45 268 t.Errorf("Error saving profile in %T: %s", store, err)
paddy@45 269 }
paddy@116 270 err = context.SaveProfile(profile3)
paddy@45 271 if err != nil {
paddy@45 272 t.Errorf("Error saving profile in %T: %s", store, err)
paddy@45 273 }
paddy@116 274 err = context.UpdateProfiles([]uuid.ID{profile1.ID, profile3.ID}, change)
paddy@45 275 if err != nil {
paddy@45 276 t.Errorf("Error updating profile in %T: %s", store, err)
paddy@45 277 }
paddy@45 278 profile1.Compromised = truth
paddy@45 279 profile3.Compromised = truth
paddy@116 280 retrieved, err := context.GetProfileByID(profile1.ID)
paddy@45 281 if err != nil {
paddy@45 282 t.Errorf("Error getting profile from %T: %s", store, err)
paddy@45 283 }
paddy@45 284 match, field, expected, got := compareProfiles(profile1, retrieved)
paddy@45 285 if !match {
paddy@45 286 t.Errorf("Expected field `%s` to be `%v`, got `%v` from %T", field, expected, got, store)
paddy@45 287 }
paddy@116 288 retrieved, err = context.GetProfileByID(profile2.ID)
paddy@45 289 if err != nil {
paddy@45 290 t.Errorf("Error getting profile from %T: %s", store, err)
paddy@45 291 }
paddy@45 292 match, field, expected, got = compareProfiles(profile2, retrieved)
paddy@45 293 if !match {
paddy@45 294 t.Errorf("Expected field `%s` to be `%v`, got `%v` from %T", field, expected, got, store)
paddy@45 295 }
paddy@116 296 retrieved, err = context.GetProfileByID(profile3.ID)
paddy@45 297 if err != nil {
paddy@45 298 t.Errorf("Error getting profile from %T: %s", store, err)
paddy@45 299 }
paddy@45 300 match, field, expected, got = compareProfiles(profile3, retrieved)
paddy@45 301 if !match {
paddy@45 302 t.Errorf("Expected field `%s` to be `%v`, got `%v` from %T", field, expected, got, store)
paddy@45 303 }
paddy@45 304 }
paddy@45 305 }
paddy@46 306
paddy@46 307 func TestProfileStoreLoginSuccess(t *testing.T) {
paddy@46 308 t.Parallel()
paddy@46 309 login := Login{
paddy@46 310 Type: "type",
paddy@46 311 Value: "value",
paddy@46 312 ProfileID: uuid.NewID(),
paddy@46 313 Created: time.Now().Add(-1 * time.Hour),
paddy@46 314 LastUsed: time.Now().Add(-1 * time.Minute),
paddy@46 315 }
paddy@46 316 for _, store := range profileStores {
paddy@116 317 context := Context{profiles: store}
paddy@116 318 err := context.AddLogin(login)
paddy@46 319 if err != nil {
paddy@46 320 t.Errorf("Error adding login to %T: %s", store, err)
paddy@46 321 }
paddy@116 322 err = context.AddLogin(login)
paddy@46 323 if err != ErrLoginAlreadyExists {
paddy@46 324 t.Errorf("Expected ErrLoginAlreadyExists from %T, got %+v", store, err)
paddy@46 325 }
paddy@116 326 retrieved, err := context.ListLogins(login.ProfileID, 10, 0)
paddy@46 327 if err != nil {
paddy@46 328 t.Errorf("Error retrieving logins from %T: %s", store, err)
paddy@46 329 }
paddy@46 330 if len(retrieved) != 1 {
paddy@46 331 t.Errorf("Expected 1 login result from %T, got %d", store, len(retrieved))
paddy@46 332 }
paddy@46 333 match, field, expectation, result := compareLogins(login, retrieved[0])
paddy@46 334 if !match {
paddy@46 335 t.Errorf("Expected `%v` in the `%s` field of login retrieved from %T, got `%v`", expectation, field, store, result)
paddy@46 336 }
paddy@46 337 lastUsed := time.Now()
paddy@116 338 err = context.RecordLoginUse(login.Value, lastUsed)
paddy@46 339 if err != nil {
paddy@46 340 t.Errorf("Error recording use of login to %T: %s", store, err)
paddy@46 341 }
paddy@46 342 login.LastUsed = lastUsed
paddy@116 343 retrieved, err = context.ListLogins(login.ProfileID, 10, 0)
paddy@46 344 if err != nil {
paddy@46 345 t.Errorf("Error retrieving logins from %T: %s", store, err)
paddy@46 346 }
paddy@46 347 if len(retrieved) != 1 {
paddy@46 348 t.Errorf("Expected 1 login result from %T, got %d", store, len(retrieved))
paddy@46 349 }
paddy@46 350 match, field, expectation, result = compareLogins(login, retrieved[0])
paddy@46 351 if !match {
paddy@46 352 t.Errorf("Expected `%v` in the `%s` field of login retrieved from %T, got `%v`", expectation, field, store, result)
paddy@46 353 }
paddy@116 354 err = context.RemoveLogin(login.Value, login.ProfileID)
paddy@46 355 if err != nil {
paddy@46 356 t.Errorf("Error removing login from %T: %s", store, err)
paddy@46 357 }
paddy@116 358 retrieved, err = context.ListLogins(login.ProfileID, 10, 0)
paddy@46 359 if len(retrieved) != 0 {
paddy@46 360 t.Errorf("Expected 0 login results from %T, got %d: %+v", store, len(retrieved), retrieved)
paddy@46 361 }
paddy@116 362 err = context.RemoveLogin(login.Value, login.ProfileID)
paddy@46 363 if err != ErrLoginNotFound {
paddy@46 364 t.Errorf("Expected ErrLoginNotFound from %T, got %+v", store, err)
paddy@46 365 }
paddy@46 366 }
paddy@46 367 }
paddy@47 368
paddy@47 369 func TestProfileStoreLoginRetrieval(t *testing.T) {
paddy@47 370 t.Parallel()
paddy@47 371 profile := Profile{
paddy@47 372 ID: uuid.NewID(),
paddy@47 373 Name: "name",
paddy@47 374 Passphrase: "passphrase",
paddy@47 375 Iterations: 10000,
paddy@47 376 Salt: "salt",
paddy@47 377 PassphraseScheme: 1,
paddy@47 378 Compromised: false,
paddy@47 379 LockedUntil: time.Now().Add(time.Hour),
paddy@47 380 PassphraseReset: "passphrase reset",
paddy@47 381 PassphraseResetCreated: time.Now(),
paddy@47 382 Created: time.Now(),
paddy@47 383 LastSeen: time.Now(),
paddy@47 384 }
paddy@47 385 login := Login{
paddy@47 386 Type: "type",
paddy@47 387 Value: "value",
paddy@47 388 ProfileID: profile.ID,
paddy@47 389 Created: time.Now().Add(-1 * time.Hour),
paddy@47 390 LastUsed: time.Now().Add(-1 * time.Minute),
paddy@47 391 }
paddy@47 392 for _, store := range profileStores {
paddy@116 393 context := Context{profiles: store}
paddy@116 394 err := context.SaveProfile(profile)
paddy@47 395 if err != nil {
paddy@47 396 t.Errorf("Error saving profile in %T: %s", store, err)
paddy@47 397 }
paddy@116 398 err = context.AddLogin(login)
paddy@47 399 if err != nil {
paddy@47 400 t.Errorf("Error storing login in %T: %s", store, err)
paddy@47 401 }
paddy@116 402 retrieved, err := context.GetProfileByLogin(login.Value)
paddy@47 403 if err != nil {
paddy@47 404 t.Errorf("Error retrieving profile by login from %T: %s", store, err)
paddy@47 405 }
paddy@47 406 match, field, expectation, result := compareProfiles(profile, retrieved)
paddy@47 407 if !match {
paddy@47 408 t.Errorf("Expected `%v` in the `%s` field of profile retrieved from %T, got `%v`", expectation, field, store, result)
paddy@47 409 }
paddy@47 410 }
paddy@47 411 }
paddy@48 412
paddy@48 413 func TestProfileChangeValidation(t *testing.T) {
paddy@48 414 t.Parallel()
paddy@48 415 passphraseScheme := 1
paddy@48 416 passphraseReset := "reset"
paddy@48 417 salt := "salt"
paddy@69 418 iterations := 100
paddy@48 419 shortPassphrase := "a"
paddy@48 420 longPassphrase := "this passphrase is much too long for anyone to remember, and therefore should probably be discouraged by the software, don't you think?"
paddy@48 421 emptyName := ""
paddy@48 422 enteredName := "Paddy"
paddy@48 423 okPassphrase := "this is a decent passphrase"
paddy@48 424 compromised := true
paddy@48 425 lockedUntil := time.Now()
paddy@48 426 resetCreated := time.Now()
paddy@48 427 lastSeen := time.Now()
paddy@48 428 changes := map[*ProfileChange]error{
paddy@48 429 &ProfileChange{}: ErrEmptyChange,
paddy@48 430 &ProfileChange{PassphraseScheme: &passphraseScheme}: ErrMissingPassphrase,
paddy@48 431 &ProfileChange{PassphraseScheme: &passphraseScheme, Passphrase: &okPassphrase}: nil,
paddy@48 432 &ProfileChange{PassphraseReset: &passphraseReset}: ErrMissingPassphraseResetCreated,
paddy@48 433 &ProfileChange{PassphraseReset: &passphraseReset, PassphraseResetCreated: &resetCreated}: nil,
paddy@48 434 &ProfileChange{Salt: &salt}: ErrMissingPassphrase,
paddy@48 435 &ProfileChange{Salt: &salt, Passphrase: &okPassphrase}: nil,
paddy@48 436 &ProfileChange{Iterations: &iterations}: ErrMissingPassphrase,
paddy@48 437 &ProfileChange{Iterations: &iterations, Passphrase: &okPassphrase}: nil,
paddy@48 438 &ProfileChange{Passphrase: &shortPassphrase}: ErrPassphraseTooShort,
paddy@48 439 &ProfileChange{Passphrase: &longPassphrase}: ErrPassphraseTooLong,
paddy@48 440 &ProfileChange{Passphrase: &okPassphrase}: nil,
paddy@48 441 &ProfileChange{Name: &emptyName}: nil,
paddy@48 442 &ProfileChange{Name: &enteredName}: nil,
paddy@48 443 &ProfileChange{Compromised: &compromised}: nil,
paddy@48 444 &ProfileChange{LockedUntil: &lockedUntil}: nil,
paddy@48 445 &ProfileChange{LastSeen: &lastSeen}: nil,
paddy@48 446 &ProfileChange{PassphraseResetCreated: &resetCreated}: ErrMissingPassphraseReset,
paddy@48 447 }
paddy@48 448 for change, expectedErr := range changes {
paddy@48 449 if err := change.Validate(); err != expectedErr {
paddy@48 450 t.Errorf("Expected %+v to give an error of %v, gave %v", change, expectedErr, err)
paddy@48 451 }
paddy@48 452 }
paddy@48 453 }
paddy@48 454
paddy@48 455 func TestBulkProfileChangeValidation(t *testing.T) {
paddy@48 456 t.Parallel()
paddy@48 457 compromised := true
paddy@48 458 changes := map[*BulkProfileChange]error{
paddy@48 459 &BulkProfileChange{}: ErrEmptyChange,
paddy@48 460 &BulkProfileChange{Compromised: &compromised}: nil,
paddy@48 461 }
paddy@48 462 for change, expectedErr := range changes {
paddy@48 463 if err := change.Validate(); err != expectedErr {
paddy@48 464 t.Errorf("Expected %+v to give an error of %v, gave %v", change, expectedErr, err)
paddy@48 465 }
paddy@48 466 }
paddy@48 467 }
paddy@128 468
paddy@128 469 // BUG(paddy): We need to test the validateNewProfileRequest helper.
paddy@128 470 // BUG(paddy): We need to test the CreateProfileHandler.