auth

Paddy 2014-12-17 Parent:0a6e3f14b054 Child:5bd46746b809

107:c03b5eb3179e Go to Latest

auth/client_test.go

Update import paths. Let's just use import paths that don't need aliasing, by specifying that they're mercurial repos.

History
paddy@31 1 package auth
paddy@31 2
paddy@31 3 import (
paddy@39 4 "fmt"
paddy@41 5 "net/url"
paddy@82 6 "sort"
paddy@31 7 "testing"
paddy@41 8 "time"
paddy@31 9
paddy@107 10 "code.secondbit.org/uuid.hg"
paddy@31 11 )
paddy@31 12
paddy@39 13 const (
paddy@39 14 clientChangeSecret = 1 << iota
paddy@39 15 clientChangeOwnerID
paddy@39 16 clientChangeName
paddy@39 17 clientChangeLogo
paddy@39 18 clientChangeWebsite
paddy@39 19 )
paddy@39 20
paddy@57 21 var clientStores = []clientStore{NewMemstore()}
paddy@31 22
paddy@33 23 func compareClients(client1, client2 Client) (success bool, field string, val1, val2 interface{}) {
paddy@33 24 if !client1.ID.Equal(client2.ID) {
paddy@33 25 return false, "ID", client1.ID, client2.ID
paddy@33 26 }
paddy@33 27 if client1.Secret != client2.Secret {
paddy@33 28 return false, "secret", client1.Secret, client2.Secret
paddy@33 29 }
paddy@33 30 if !client1.OwnerID.Equal(client2.OwnerID) {
paddy@33 31 return false, "owner ID", client1.OwnerID, client2.OwnerID
paddy@33 32 }
paddy@33 33 if client1.Name != client2.Name {
paddy@33 34 return false, "name", client1.Name, client2.Name
paddy@33 35 }
paddy@33 36 if client1.Logo != client2.Logo {
paddy@33 37 return false, "logo", client1.Logo, client2.Logo
paddy@33 38 }
paddy@33 39 if client1.Website != client2.Website {
paddy@33 40 return false, "website", client1.Website, client2.Website
paddy@33 41 }
paddy@41 42 if client1.Type != client2.Type {
paddy@41 43 return false, "type", client1.Type, client2.Type
paddy@41 44 }
paddy@41 45 return true, "", nil, nil
paddy@41 46 }
paddy@41 47
paddy@41 48 func compareEndpoints(endpoint1, endpoint2 Endpoint) (success bool, field string, val1, val2 interface{}) {
paddy@41 49 if !endpoint1.ID.Equal(endpoint2.ID) {
paddy@41 50 return false, "ID", endpoint1.ID, endpoint2.ID
paddy@41 51 }
paddy@41 52 if !endpoint1.ClientID.Equal(endpoint2.ClientID) {
paddy@41 53 return false, "OwnerID", endpoint1.ClientID, endpoint2.ClientID
paddy@41 54 }
paddy@41 55 if !endpoint1.Added.Equal(endpoint2.Added) {
paddy@41 56 return false, "Added", endpoint1.Added, endpoint2.Added
paddy@41 57 }
paddy@41 58 if endpoint1.URI.String() != endpoint2.URI.String() {
paddy@41 59 return false, "URI", endpoint1.URI, endpoint2.URI
paddy@41 60 }
paddy@33 61 return true, "", nil, nil
paddy@33 62 }
paddy@33 63
paddy@31 64 func TestClientStoreSuccess(t *testing.T) {
paddy@36 65 t.Parallel()
paddy@31 66 client := Client{
paddy@41 67 ID: uuid.NewID(),
paddy@41 68 Secret: "secret",
paddy@41 69 OwnerID: uuid.NewID(),
paddy@41 70 Name: "name",
paddy@41 71 Logo: "logo",
paddy@41 72 Website: "website",
paddy@31 73 }
paddy@31 74 for _, store := range clientStores {
paddy@57 75 err := store.saveClient(client)
paddy@31 76 if err != nil {
paddy@41 77 t.Fatalf("Error saving client to %T: %s", store, err)
paddy@31 78 }
paddy@57 79 err = store.saveClient(client)
paddy@33 80 if err != ErrClientAlreadyExists {
paddy@41 81 t.Fatalf("Expected ErrClientAlreadyExists, got %v from %T", err, store)
paddy@33 82 }
paddy@57 83 retrieved, err := store.getClient(client.ID)
paddy@31 84 if err != nil {
paddy@41 85 t.Fatalf("Error retrieving client from %T: %s", store, err)
paddy@31 86 }
paddy@33 87 success, field, expectation, result := compareClients(client, retrieved)
paddy@33 88 if !success {
paddy@41 89 t.Fatalf("Expected field %s to be %v, but %T returned %v", field, expectation, store, result)
paddy@33 90 }
paddy@57 91 clients, err := store.listClientsByOwner(client.OwnerID, 25, 0)
paddy@31 92 if err != nil {
paddy@41 93 t.Fatalf("Error retrieving clients by owner from %T: %s", store, err)
paddy@31 94 }
paddy@31 95 if len(clients) != 1 {
paddy@41 96 t.Fatalf("Expected 1 client in response from %T, got %+v", store, clients)
paddy@31 97 }
paddy@33 98 success, field, expectation, result = compareClients(client, clients[0])
paddy@33 99 if !success {
paddy@41 100 t.Fatalf("Expected field %s to be %v, but %T returned %v", field, expectation, store, result)
paddy@33 101 }
paddy@57 102 err = store.deleteClient(client.ID)
paddy@31 103 if err != nil {
paddy@41 104 t.Fatalf("Error deleting client from %T: %s", store, err)
paddy@31 105 }
paddy@57 106 err = store.deleteClient(client.ID)
paddy@33 107 if err != ErrClientNotFound {
paddy@41 108 t.Fatalf("Expected ErrClientNotFound, got %s from %T", err, store)
paddy@33 109 }
paddy@57 110 retrieved, err = store.getClient(client.ID)
paddy@31 111 if err != ErrClientNotFound {
paddy@41 112 t.Fatalf("Expected ErrClientNotFound from %T, got %+v and %s", store, retrieved, err)
paddy@31 113 }
paddy@57 114 clients, err = store.listClientsByOwner(client.OwnerID, 25, 0)
paddy@31 115 if err != nil {
paddy@41 116 t.Fatalf("Error listing clients by owner from %T: %s", store, err)
paddy@31 117 }
paddy@31 118 if len(clients) != 0 {
paddy@41 119 t.Fatalf("Expected 0 clients in response from %T, got %+v", store, clients)
paddy@41 120 }
paddy@41 121 }
paddy@41 122 }
paddy@41 123
paddy@41 124 func TestEndpointStoreSuccess(t *testing.T) {
paddy@41 125 t.Parallel()
paddy@41 126 client := Client{
paddy@41 127 ID: uuid.NewID(),
paddy@41 128 Secret: "secret",
paddy@41 129 OwnerID: uuid.NewID(),
paddy@41 130 Name: "name",
paddy@41 131 Logo: "logo",
paddy@41 132 Website: "website",
paddy@41 133 }
paddy@41 134 uri1, _ := url.Parse("https://www.example.com/")
paddy@41 135 uri2, _ := url.Parse("https://www.example.com/my/full/path")
paddy@41 136 endpoint1 := Endpoint{
paddy@41 137 ID: uuid.NewID(),
paddy@41 138 ClientID: client.ID,
paddy@41 139 Added: time.Now(),
paddy@41 140 URI: *uri1,
paddy@41 141 }
paddy@41 142 endpoint2 := Endpoint{
paddy@41 143 ID: uuid.NewID(),
paddy@41 144 ClientID: client.ID,
paddy@41 145 Added: time.Now(),
paddy@41 146 URI: *uri2,
paddy@41 147 }
paddy@41 148 for _, store := range clientStores {
paddy@57 149 err := store.saveClient(client)
paddy@41 150 if err != nil {
paddy@41 151 t.Fatalf("Error saving client to %T: %s", store, err)
paddy@41 152 }
paddy@57 153 err = store.addEndpoint(client.ID, endpoint1)
paddy@41 154 if err != nil {
paddy@41 155 t.Fatalf("Error adding endpoint to client in %T: %s", store, err)
paddy@41 156 }
paddy@57 157 endpoints, err := store.listEndpoints(client.ID, 10, 0)
paddy@41 158 if err != nil {
paddy@41 159 t.Fatalf("Error retrieving endpoints from %T: %s", store, err)
paddy@41 160 }
paddy@41 161 if len(endpoints) != 1 {
paddy@41 162 t.Fatalf("Expected %d endpoints, got %+v from %T", 1, endpoints, store)
paddy@41 163 }
paddy@41 164 success, field, expectation, result := compareEndpoints(endpoint1, endpoints[0])
paddy@41 165 if !success {
paddy@41 166 t.Fatalf("Expected field %s to be %v, but %T returned %v", field, expectation, store, result)
paddy@41 167 }
paddy@57 168 err = store.addEndpoint(client.ID, endpoint2)
paddy@41 169 if err != nil {
paddy@41 170 t.Fatalf("Error adding endpoint to client in %T: %s", store, err)
paddy@41 171 }
paddy@57 172 endpoints, err = store.listEndpoints(client.ID, 10, 0)
paddy@41 173 if err != nil {
paddy@41 174 t.Fatalf("Error retrieving endpoints from %T: %s", store, err)
paddy@41 175 }
paddy@41 176 if len(endpoints) != 2 {
paddy@41 177 t.Fatalf("Expected %d endpoints, got %+v from %T", 2, endpoints, store)
paddy@41 178 }
paddy@41 179 sortedEnd := sortedEndpoints(endpoints)
paddy@41 180 sort.Sort(sortedEnd)
paddy@41 181 endpoints = []Endpoint(sortedEnd)
paddy@41 182 success, field, expectation, result = compareEndpoints(endpoint1, endpoints[0])
paddy@41 183 if !success {
paddy@41 184 t.Fatalf("Expected field %s to be %v, but %T returned %v", field, expectation, store, result)
paddy@41 185 }
paddy@41 186 success, field, expectation, result = compareEndpoints(endpoint2, endpoints[1])
paddy@41 187 if !success {
paddy@41 188 t.Fatalf("Expected field %s to be %v, but %T returned %v", field, expectation, store, result)
paddy@41 189 }
paddy@57 190 err = store.removeEndpoint(client.ID, endpoint1.ID)
paddy@41 191 if err != nil {
paddy@41 192 t.Fatalf("Error removing endpoint from client in %T: %s", store, err)
paddy@41 193 }
paddy@57 194 endpoints, err = store.listEndpoints(client.ID, 10, 0)
paddy@41 195 if err != nil {
paddy@41 196 t.Fatalf("Error listing endpoints in %T: %s", store, err)
paddy@41 197 }
paddy@41 198 if len(endpoints) != 1 {
paddy@41 199 t.Fatalf("Expected %d endpoints, got %+v from %T", 1, endpoints, store)
paddy@41 200 }
paddy@41 201 success, field, expectation, result = compareEndpoints(endpoint2, endpoints[0])
paddy@41 202 if !success {
paddy@41 203 t.Fatalf("Expected field %s to be %v, but %T returned %v", field, expectation, store, result)
paddy@41 204 }
paddy@57 205 err = store.removeEndpoint(client.ID, endpoint2.ID)
paddy@41 206 if err != nil {
paddy@41 207 t.Fatalf("Error removing endpoint from client in %T: %s", store, err)
paddy@41 208 }
paddy@57 209 endpoints, err = store.listEndpoints(client.ID, 10, 0)
paddy@41 210 if err != nil {
paddy@41 211 t.Fatalf("Error listing endpoints in %T: %s", store, err)
paddy@41 212 }
paddy@41 213 if len(endpoints) != 0 {
paddy@41 214 t.Fatalf("Expected %d endpoints, got %+v from %T", 0, endpoints, store)
paddy@31 215 }
paddy@31 216 }
paddy@31 217 }
paddy@39 218
paddy@39 219 func TestClientUpdates(t *testing.T) {
paddy@39 220 t.Parallel()
paddy@41 221 variations := 1 << 5
paddy@39 222 client := Client{
paddy@41 223 ID: uuid.NewID(),
paddy@41 224 Secret: "secret",
paddy@41 225 OwnerID: uuid.NewID(),
paddy@41 226 Name: "name",
paddy@41 227 Logo: "logo",
paddy@41 228 Website: "website",
paddy@39 229 }
paddy@39 230 for i := 0; i < variations; i++ {
paddy@41 231 var secret, name, logo, website string
paddy@39 232 change := ClientChange{}
paddy@39 233 expectation := client
paddy@39 234 result := client
paddy@39 235 if i&clientChangeSecret != 0 {
paddy@39 236 secret = fmt.Sprintf("secret-%d", i)
paddy@39 237 change.Secret = &secret
paddy@39 238 expectation.Secret = secret
paddy@39 239 }
paddy@39 240 if i&clientChangeOwnerID != 0 {
paddy@39 241 change.OwnerID = uuid.NewID()
paddy@39 242 expectation.OwnerID = change.OwnerID
paddy@39 243 }
paddy@39 244 if i&clientChangeName != 0 {
paddy@39 245 name = fmt.Sprintf("name-%d", i)
paddy@39 246 change.Name = &name
paddy@39 247 expectation.Name = name
paddy@39 248 }
paddy@39 249 if i&clientChangeLogo != 0 {
paddy@39 250 logo = fmt.Sprintf("logo-%d", i)
paddy@39 251 change.Logo = &logo
paddy@39 252 expectation.Logo = logo
paddy@39 253 }
paddy@39 254 if i&clientChangeWebsite != 0 {
paddy@39 255 website = fmt.Sprintf("website-%d", i)
paddy@39 256 change.Website = &website
paddy@39 257 expectation.Website = website
paddy@39 258 }
paddy@39 259 result.ApplyChange(change)
paddy@39 260 match, field, expected, got := compareClients(expectation, result)
paddy@39 261 if !match {
paddy@41 262 t.Fatalf("Expected field `%s` to be `%v`, got `%v`", field, expected, got)
paddy@39 263 }
paddy@39 264 for _, store := range clientStores {
paddy@57 265 err := store.saveClient(client)
paddy@39 266 if err != nil {
paddy@41 267 t.Fatalf("Error saving client in %T: %s", store, err)
paddy@39 268 }
paddy@57 269 err = store.updateClient(client.ID, change)
paddy@39 270 if err != nil {
paddy@41 271 t.Fatalf("Error updating client in %T: %s", store, err)
paddy@39 272 }
paddy@57 273 retrieved, err := store.getClient(client.ID)
paddy@39 274 if err != nil {
paddy@41 275 t.Fatalf("Error getting profile from %T: %s", store, err)
paddy@39 276 }
paddy@39 277 match, field, expected, got = compareClients(expectation, retrieved)
paddy@39 278 if !match {
paddy@41 279 t.Fatalf("Expected field `%s` to be `%v`, got `%v` from %T", field, expected, got, store)
paddy@39 280 }
paddy@57 281 err = store.deleteClient(client.ID)
paddy@39 282 if err != nil {
paddy@41 283 t.Fatalf("Error deleting client from %T: %s", store, err)
paddy@39 284 }
paddy@57 285 err = store.updateClient(client.ID, change)
paddy@39 286 if err != ErrClientNotFound {
paddy@41 287 t.Fatalf("Expected ErrClientNotFound, got %v from %T", err, store)
paddy@39 288 }
paddy@39 289 }
paddy@39 290 }
paddy@39 291 }
paddy@41 292
paddy@41 293 func TestClientEndpointChecks(t *testing.T) {
paddy@41 294 t.Parallel()
paddy@41 295 client := Client{
paddy@41 296 ID: uuid.NewID(),
paddy@41 297 Secret: "secret",
paddy@41 298 OwnerID: uuid.NewID(),
paddy@41 299 Name: "name",
paddy@41 300 Logo: "logo",
paddy@41 301 Website: "website",
paddy@41 302 }
paddy@41 303 uri1, _ := url.Parse("https://www.example.com/first")
paddy@41 304 uri2, _ := url.Parse("https://www.example.com/my/full/path")
paddy@41 305 endpoint1 := Endpoint{
paddy@41 306 ID: uuid.NewID(),
paddy@41 307 ClientID: client.ID,
paddy@41 308 Added: time.Now(),
paddy@41 309 URI: *uri1,
paddy@41 310 }
paddy@41 311 endpoint2 := Endpoint{
paddy@41 312 ID: uuid.NewID(),
paddy@41 313 ClientID: client.ID,
paddy@41 314 Added: time.Now(),
paddy@41 315 URI: *uri2,
paddy@41 316 }
paddy@41 317 candidates := map[string]bool{
paddy@41 318 "https://www.example.com/": false,
paddy@41 319 "https://www.example.com/first": true,
paddy@58 320 "https://www.example.com/first/extra/path": false,
paddy@41 321 "https://www.example.com/my": false,
paddy@41 322 "https://www.example.com/my/full/path": true,
paddy@41 323 }
paddy@41 324 for _, store := range clientStores {
paddy@57 325 err := store.saveClient(client)
paddy@41 326 if err != nil {
paddy@41 327 t.Fatalf("Error saving client in %T: %s", store, err)
paddy@41 328 }
paddy@57 329 err = store.addEndpoint(client.ID, endpoint1)
paddy@41 330 if err != nil {
paddy@41 331 t.Fatalf("Error saving endpoint in %T: %s", store, err)
paddy@41 332 }
paddy@57 333 err = store.addEndpoint(client.ID, endpoint2)
paddy@41 334 if err != nil {
paddy@41 335 t.Fatalf("Error saving endpoint in %T: %s", store, err)
paddy@41 336 }
paddy@41 337 for candidate, expectation := range candidates {
paddy@58 338 result, err := store.checkEndpoint(client.ID, candidate)
paddy@54 339 if err != nil {
paddy@54 340 t.Fatalf("Error checking endpoint %s in %T: %s", candidate, store, err)
paddy@54 341 }
paddy@54 342 if result != expectation {
paddy@54 343 expectStr := "no"
paddy@54 344 resultStr := "a"
paddy@54 345 if expectation {
paddy@54 346 expectStr = "a"
paddy@54 347 resultStr = "no"
paddy@54 348 }
paddy@54 349 t.Errorf("Expected %s match for %s in %T, got %s match", expectStr, candidate, store, resultStr)
paddy@54 350 }
paddy@54 351 }
paddy@54 352 }
paddy@54 353 }
paddy@54 354
paddy@54 355 func TestClientEndpointChecksStrict(t *testing.T) {
paddy@54 356 t.Parallel()
paddy@54 357 client := Client{
paddy@54 358 ID: uuid.NewID(),
paddy@54 359 Secret: "secret",
paddy@54 360 OwnerID: uuid.NewID(),
paddy@54 361 Name: "name",
paddy@54 362 Logo: "logo",
paddy@54 363 Website: "website",
paddy@54 364 }
paddy@54 365 uri1, _ := url.Parse("https://www.example.com/first")
paddy@54 366 uri2, _ := url.Parse("https://www.example.com/my/full/path")
paddy@54 367 endpoint1 := Endpoint{
paddy@54 368 ID: uuid.NewID(),
paddy@54 369 ClientID: client.ID,
paddy@54 370 Added: time.Now(),
paddy@54 371 URI: *uri1,
paddy@54 372 }
paddy@54 373 endpoint2 := Endpoint{
paddy@54 374 ID: uuid.NewID(),
paddy@54 375 ClientID: client.ID,
paddy@54 376 Added: time.Now(),
paddy@54 377 URI: *uri2,
paddy@54 378 }
paddy@54 379 candidates := map[string]bool{
paddy@54 380 "https://www.example.com/": false,
paddy@54 381 "https://www.example.com/first": true,
paddy@54 382 "https://www.example.com/first/extra/path": false,
paddy@54 383 "https://www.example.com/my": false,
paddy@54 384 "https://www.example.com/my/full/path": true,
paddy@54 385 }
paddy@54 386 for _, store := range clientStores {
paddy@57 387 err := store.saveClient(client)
paddy@54 388 if err != nil {
paddy@54 389 t.Fatalf("Error saving client in %T: %s", store, err)
paddy@54 390 }
paddy@57 391 err = store.addEndpoint(client.ID, endpoint1)
paddy@54 392 if err != nil {
paddy@54 393 t.Fatalf("Error saving endpoint in %T: %s", store, err)
paddy@54 394 }
paddy@57 395 err = store.addEndpoint(client.ID, endpoint2)
paddy@54 396 if err != nil {
paddy@54 397 t.Fatalf("Error saving endpoint in %T: %s", store, err)
paddy@54 398 }
paddy@54 399 for candidate, expectation := range candidates {
paddy@58 400 result, err := store.checkEndpoint(client.ID, candidate)
paddy@41 401 if err != nil {
paddy@41 402 t.Fatalf("Error checking endpoint %s in %T: %s", candidate, store, err)
paddy@41 403 }
paddy@41 404 if result != expectation {
paddy@41 405 expectStr := "no"
paddy@41 406 resultStr := "a"
paddy@41 407 if expectation {
paddy@41 408 expectStr = "a"
paddy@41 409 resultStr = "no"
paddy@41 410 }
paddy@41 411 t.Errorf("Expected %s match for %s in %T, got %s match", expectStr, candidate, store, resultStr)
paddy@41 412 }
paddy@41 413 }
paddy@41 414 }
paddy@41 415 }
paddy@43 416
paddy@43 417 func TestClientChangeValidation(t *testing.T) {
paddy@43 418 t.Parallel()
paddy@43 419 change := ClientChange{}
paddy@43 420 if err := change.Validate(); err != ErrEmptyChange {
paddy@43 421 t.Errorf("Expected %s to give an error of %s, gave %s", "empty change", ErrEmptyChange, err)
paddy@43 422 }
paddy@43 423 names := map[string]error{
paddy@43 424 "a": ErrClientNameTooShort,
paddy@43 425 "ab": nil,
paddy@43 426 "abc": nil,
paddy@43 427 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopq": ErrClientNameTooLong,
paddy@43 428 }
paddy@43 429 for name, expectation := range names {
paddy@43 430 change = ClientChange{Name: &name}
paddy@43 431 if err := change.Validate(); err != expectation {
paddy@43 432 t.Errorf("Expected %s to give an error of %s, gave %s", name, expectation, err)
paddy@43 433 }
paddy@43 434 }
paddy@43 435 longPath := ""
paddy@43 436 for i := 0; i < 1025; i++ {
paddy@43 437 longPath = fmt.Sprintf("%s%d", longPath, i)
paddy@43 438 }
paddy@43 439 logos := map[string]error{
paddy@43 440 "https://www.example.com/" + longPath: ErrClientLogoTooLong,
paddy@43 441 "https://www.example.com/ab": nil,
paddy@43 442 "www.example.com/ab": ErrClientLogoNotURL,
paddy@43 443 "test": ErrClientLogoNotURL,
paddy@43 444 "": nil,
paddy@43 445 }
paddy@43 446 for logo, expectation := range logos {
paddy@43 447 change = ClientChange{Logo: &logo}
paddy@43 448 if err := change.Validate(); err != expectation {
paddy@43 449 t.Errorf("Expected %s to give an error of %s, gave %s", logo, expectation, err)
paddy@43 450 }
paddy@43 451 }
paddy@43 452 websites := map[string]error{
paddy@43 453 "https://www.example.com/" + longPath: ErrClientWebsiteTooLong,
paddy@43 454 "https://www.example.com/ab": nil,
paddy@43 455 "www.example.com/ab": ErrClientWebsiteNotURL,
paddy@43 456 "test": ErrClientWebsiteNotURL,
paddy@43 457 "": nil,
paddy@43 458 }
paddy@43 459 for website, expectation := range websites {
paddy@43 460 change = ClientChange{Website: &website}
paddy@43 461 if err := change.Validate(); err != expectation {
paddy@43 462 t.Errorf("Expected %s to give an error of %s, gave %s", website, expectation, err)
paddy@43 463 }
paddy@43 464 }
paddy@43 465 }