github.com/huaweicloud/golangsdk@v0.0.0-20210831081626-d823fe11ceba/openstack/identity/v3/tokens/testing/requests_test.go (about) 1 package testing 2 3 import ( 4 "fmt" 5 "net/http" 6 "testing" 7 "time" 8 9 "github.com/huaweicloud/golangsdk" 10 "github.com/huaweicloud/golangsdk/openstack/identity/v3/tokens" 11 "github.com/huaweicloud/golangsdk/testhelper" 12 ) 13 14 // authTokenPost verifies that providing certain AuthOptions and Scope results in an expected JSON structure. 15 func authTokenPost(t *testing.T, options tokens.AuthOptions, scope *tokens.Scope, requestJSON string) { 16 testhelper.SetupHTTP() 17 defer testhelper.TeardownHTTP() 18 19 client := golangsdk.ServiceClient{ 20 ProviderClient: &golangsdk.ProviderClient{}, 21 Endpoint: testhelper.Endpoint(), 22 } 23 24 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 25 testhelper.TestMethod(t, r, "POST") 26 testhelper.TestHeader(t, r, "Content-Type", "application/json") 27 testhelper.TestHeader(t, r, "Accept", "application/json") 28 testhelper.TestJSONRequest(t, r, requestJSON) 29 30 w.WriteHeader(http.StatusCreated) 31 fmt.Fprintf(w, `{ 32 "token": { 33 "expires_at": "2014-10-02T13:45:00.000000Z" 34 } 35 }`) 36 }) 37 38 if scope != nil { 39 options.Scope = *scope 40 } 41 42 expected := &tokens.Token{ 43 ExpiresAt: time.Date(2014, 10, 2, 13, 45, 0, 0, time.UTC), 44 } 45 actual, err := tokens.Create(&client, &options).Extract() 46 testhelper.AssertNoErr(t, err) 47 testhelper.CheckDeepEquals(t, expected, actual) 48 } 49 50 func authTokenPostErr(t *testing.T, options tokens.AuthOptions, scope *tokens.Scope, includeToken bool, expectedErr error) { 51 testhelper.SetupHTTP() 52 defer testhelper.TeardownHTTP() 53 54 client := golangsdk.ServiceClient{ 55 ProviderClient: &golangsdk.ProviderClient{}, 56 Endpoint: testhelper.Endpoint(), 57 } 58 if includeToken { 59 client.TokenID = "abcdef123456" 60 } 61 62 if scope != nil { 63 options.Scope = *scope 64 } 65 66 _, err := tokens.Create(&client, &options).Extract() 67 if err == nil { 68 t.Errorf("Create did NOT return an error") 69 } 70 if err != expectedErr { 71 t.Errorf("Create returned an unexpected error: wanted %v, got %v", expectedErr, err) 72 } 73 } 74 75 func TestCreateUserIDAndPassword(t *testing.T) { 76 authTokenPost(t, tokens.AuthOptions{UserID: "me", Password: "squirrel!"}, nil, ` 77 { 78 "auth": { 79 "identity": { 80 "methods": ["password"], 81 "password": { 82 "user": { "id": "me", "password": "squirrel!" } 83 } 84 } 85 } 86 } 87 `) 88 } 89 90 func TestCreateUsernameDomainIDPassword(t *testing.T) { 91 authTokenPost(t, tokens.AuthOptions{Username: "fakey", Password: "notpassword", DomainID: "abc123"}, nil, ` 92 { 93 "auth": { 94 "identity": { 95 "methods": ["password"], 96 "password": { 97 "user": { 98 "domain": { 99 "id": "abc123" 100 }, 101 "name": "fakey", 102 "password": "notpassword" 103 } 104 } 105 } 106 } 107 } 108 `) 109 } 110 111 func TestCreateUsernameDomainNamePassword(t *testing.T) { 112 authTokenPost(t, tokens.AuthOptions{Username: "frank", Password: "swordfish", DomainName: "spork.net"}, nil, ` 113 { 114 "auth": { 115 "identity": { 116 "methods": ["password"], 117 "password": { 118 "user": { 119 "domain": { 120 "name": "spork.net" 121 }, 122 "name": "frank", 123 "password": "swordfish" 124 } 125 } 126 } 127 } 128 } 129 `) 130 } 131 132 func TestCreateTokenID(t *testing.T) { 133 authTokenPost(t, tokens.AuthOptions{TokenID: "12345abcdef"}, nil, ` 134 { 135 "auth": { 136 "identity": { 137 "methods": ["token"], 138 "token": { 139 "id": "12345abcdef" 140 } 141 } 142 } 143 } 144 `) 145 } 146 147 func TestCreateProjectIDScope(t *testing.T) { 148 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 149 scope := &tokens.Scope{ProjectID: "123456"} 150 authTokenPost(t, options, scope, ` 151 { 152 "auth": { 153 "identity": { 154 "methods": ["password"], 155 "password": { 156 "user": { 157 "id": "fenris", 158 "password": "g0t0h311" 159 } 160 } 161 }, 162 "scope": { 163 "project": { 164 "id": "123456" 165 } 166 } 167 } 168 } 169 `) 170 } 171 172 func TestCreateDomainIDScope(t *testing.T) { 173 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 174 scope := &tokens.Scope{DomainID: "1000"} 175 authTokenPost(t, options, scope, ` 176 { 177 "auth": { 178 "identity": { 179 "methods": ["password"], 180 "password": { 181 "user": { 182 "id": "fenris", 183 "password": "g0t0h311" 184 } 185 } 186 }, 187 "scope": { 188 "domain": { 189 "id": "1000" 190 } 191 } 192 } 193 } 194 `) 195 } 196 197 func TestCreateDomainNameScope(t *testing.T) { 198 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 199 scope := &tokens.Scope{DomainName: "evil-plans"} 200 authTokenPost(t, options, scope, ` 201 { 202 "auth": { 203 "identity": { 204 "methods": ["password"], 205 "password": { 206 "user": { 207 "id": "fenris", 208 "password": "g0t0h311" 209 } 210 } 211 }, 212 "scope": { 213 "domain": { 214 "name": "evil-plans" 215 } 216 } 217 } 218 } 219 `) 220 } 221 222 func TestCreateProjectNameAndDomainIDScope(t *testing.T) { 223 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 224 scope := &tokens.Scope{ProjectName: "world-domination", DomainID: "1000"} 225 authTokenPost(t, options, scope, ` 226 { 227 "auth": { 228 "identity": { 229 "methods": ["password"], 230 "password": { 231 "user": { 232 "id": "fenris", 233 "password": "g0t0h311" 234 } 235 } 236 }, 237 "scope": { 238 "project": { 239 "domain": { 240 "id": "1000" 241 }, 242 "name": "world-domination" 243 } 244 } 245 } 246 } 247 `) 248 } 249 250 func TestCreateProjectNameAndDomainNameScope(t *testing.T) { 251 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 252 scope := &tokens.Scope{ProjectName: "world-domination", DomainName: "evil-plans"} 253 authTokenPost(t, options, scope, ` 254 { 255 "auth": { 256 "identity": { 257 "methods": ["password"], 258 "password": { 259 "user": { 260 "id": "fenris", 261 "password": "g0t0h311" 262 } 263 } 264 }, 265 "scope": { 266 "project": { 267 "domain": { 268 "name": "evil-plans" 269 }, 270 "name": "world-domination" 271 } 272 } 273 } 274 } 275 `) 276 } 277 278 func TestCreateExtractsTokenFromResponse(t *testing.T) { 279 testhelper.SetupHTTP() 280 defer testhelper.TeardownHTTP() 281 282 client := golangsdk.ServiceClient{ 283 ProviderClient: &golangsdk.ProviderClient{}, 284 Endpoint: testhelper.Endpoint(), 285 } 286 287 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 288 w.Header().Add("X-Subject-Token", "aaa111") 289 290 w.WriteHeader(http.StatusCreated) 291 fmt.Fprintf(w, `{ 292 "token": { 293 "expires_at": "2014-10-02T13:45:00.000000Z" 294 } 295 }`) 296 }) 297 298 options := tokens.AuthOptions{UserID: "me", Password: "shhh"} 299 token, err := tokens.Create(&client, &options).Extract() 300 if err != nil { 301 t.Fatalf("Create returned an error: %v", err) 302 } 303 304 if token.ID != "aaa111" { 305 t.Errorf("Expected token to be aaa111, but was %s", token.ID) 306 } 307 } 308 309 func TestCreateFailureEmptyAuth(t *testing.T) { 310 authTokenPostErr(t, tokens.AuthOptions{}, nil, false, golangsdk.ErrMissingPassword{}) 311 } 312 313 func TestCreateFailureTokenIDUsername(t *testing.T) { 314 authTokenPostErr(t, tokens.AuthOptions{Username: "something", TokenID: "12345"}, nil, true, golangsdk.ErrUsernameWithToken{}) 315 } 316 317 func TestCreateFailureTokenIDUserID(t *testing.T) { 318 authTokenPostErr(t, tokens.AuthOptions{UserID: "something", TokenID: "12345"}, nil, true, golangsdk.ErrUserIDWithToken{}) 319 } 320 321 func TestCreateFailureMissingUser(t *testing.T) { 322 options := tokens.AuthOptions{Password: "supersecure"} 323 authTokenPostErr(t, options, nil, false, golangsdk.ErrUsernameOrUserID{}) 324 } 325 326 func TestCreateFailureBothUser(t *testing.T) { 327 options := tokens.AuthOptions{ 328 Password: "supersecure", 329 Username: "oops", 330 UserID: "redundancy", 331 } 332 authTokenPostErr(t, options, nil, false, golangsdk.ErrUsernameOrUserID{}) 333 } 334 335 func TestCreateFailureMissingDomain(t *testing.T) { 336 options := tokens.AuthOptions{ 337 Password: "supersecure", 338 Username: "notuniqueenough", 339 } 340 authTokenPostErr(t, options, nil, false, golangsdk.ErrDomainIDOrDomainName{}) 341 } 342 343 func TestCreateFailureBothDomain(t *testing.T) { 344 options := tokens.AuthOptions{ 345 Password: "supersecure", 346 Username: "someone", 347 DomainID: "hurf", 348 DomainName: "durf", 349 } 350 authTokenPostErr(t, options, nil, false, golangsdk.ErrDomainIDOrDomainName{}) 351 } 352 353 func TestCreateFailureUserIDDomainID(t *testing.T) { 354 options := tokens.AuthOptions{ 355 UserID: "100", 356 Password: "stuff", 357 DomainID: "oops", 358 } 359 authTokenPostErr(t, options, nil, false, golangsdk.ErrDomainIDWithUserID{}) 360 } 361 362 func TestCreateFailureUserIDDomainName(t *testing.T) { 363 options := tokens.AuthOptions{ 364 UserID: "100", 365 Password: "sssh", 366 DomainName: "oops", 367 } 368 authTokenPostErr(t, options, nil, false, golangsdk.ErrDomainNameWithUserID{}) 369 } 370 371 func TestCreateFailureScopeProjectNameAlone(t *testing.T) { 372 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 373 scope := &tokens.Scope{ProjectName: "notenough"} 374 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeDomainIDOrDomainName{}) 375 } 376 377 func TestCreateFailureScopeProjectNameAndID(t *testing.T) { 378 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 379 scope := &tokens.Scope{ProjectName: "whoops", ProjectID: "toomuch", DomainID: "1234"} 380 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeProjectIDOrProjectName{}) 381 } 382 383 func TestCreateFailureScopeProjectIDAndDomainID(t *testing.T) { 384 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 385 scope := &tokens.Scope{ProjectID: "toomuch", DomainID: "notneeded"} 386 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeProjectIDAlone{}) 387 } 388 389 func TestCreateFailureScopeProjectIDAndDomainNAme(t *testing.T) { 390 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 391 scope := &tokens.Scope{ProjectID: "toomuch", DomainName: "notneeded"} 392 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeProjectIDAlone{}) 393 } 394 395 func TestCreateFailureScopeDomainIDAndDomainName(t *testing.T) { 396 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 397 scope := &tokens.Scope{DomainID: "toomuch", DomainName: "notneeded"} 398 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeDomainIDOrDomainName{}) 399 } 400 401 /* 402 func TestCreateFailureEmptyScope(t *testing.T) { 403 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 404 scope := &tokens.Scope{} 405 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeEmpty{}) 406 } 407 */ 408 409 func TestGetRequest(t *testing.T) { 410 testhelper.SetupHTTP() 411 defer testhelper.TeardownHTTP() 412 413 client := golangsdk.ServiceClient{ 414 ProviderClient: &golangsdk.ProviderClient{ 415 TokenID: "12345abcdef", 416 }, 417 Endpoint: testhelper.Endpoint(), 418 } 419 420 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 421 testhelper.TestMethod(t, r, "GET") 422 testhelper.TestHeader(t, r, "Content-Type", "") 423 testhelper.TestHeader(t, r, "Accept", "application/json") 424 testhelper.TestHeader(t, r, "X-Auth-Token", "12345abcdef") 425 testhelper.TestHeader(t, r, "X-Subject-Token", "abcdef12345") 426 427 w.WriteHeader(http.StatusOK) 428 fmt.Fprintf(w, ` 429 { "token": { "expires_at": "2014-08-29T13:10:01.000000Z" } } 430 `) 431 }) 432 433 token, err := tokens.Get(&client, "abcdef12345").Extract() 434 if err != nil { 435 t.Errorf("Info returned an error: %v", err) 436 } 437 438 expected, _ := time.Parse(time.UnixDate, "Fri Aug 29 13:10:01 UTC 2014") 439 if token.ExpiresAt != expected { 440 t.Errorf("Expected expiration time %s, but was %s", expected.Format(time.UnixDate), time.Time(token.ExpiresAt).Format(time.UnixDate)) 441 } 442 } 443 444 func prepareAuthTokenHandler(t *testing.T, expectedMethod string, status int) golangsdk.ServiceClient { 445 client := golangsdk.ServiceClient{ 446 ProviderClient: &golangsdk.ProviderClient{ 447 TokenID: "12345abcdef", 448 }, 449 Endpoint: testhelper.Endpoint(), 450 } 451 452 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 453 testhelper.TestMethod(t, r, expectedMethod) 454 testhelper.TestHeader(t, r, "Content-Type", "") 455 testhelper.TestHeader(t, r, "Accept", "application/json") 456 testhelper.TestHeader(t, r, "X-Auth-Token", "12345abcdef") 457 testhelper.TestHeader(t, r, "X-Subject-Token", "abcdef12345") 458 459 w.WriteHeader(status) 460 }) 461 462 return client 463 } 464 465 func TestValidateRequestSuccessful(t *testing.T) { 466 testhelper.SetupHTTP() 467 defer testhelper.TeardownHTTP() 468 client := prepareAuthTokenHandler(t, "HEAD", http.StatusNoContent) 469 470 ok, err := tokens.Validate(&client, "abcdef12345") 471 if err != nil { 472 t.Errorf("Unexpected error from Validate: %v", err) 473 } 474 475 if !ok { 476 t.Errorf("Validate returned false for a valid token") 477 } 478 } 479 480 func TestValidateRequestFailure(t *testing.T) { 481 testhelper.SetupHTTP() 482 defer testhelper.TeardownHTTP() 483 client := prepareAuthTokenHandler(t, "HEAD", http.StatusNotFound) 484 485 ok, err := tokens.Validate(&client, "abcdef12345") 486 if err != nil { 487 t.Errorf("Unexpected error from Validate: %v", err) 488 } 489 490 if ok { 491 t.Errorf("Validate returned true for an invalid token") 492 } 493 } 494 495 func TestValidateRequestError(t *testing.T) { 496 testhelper.SetupHTTP() 497 defer testhelper.TeardownHTTP() 498 client := prepareAuthTokenHandler(t, "HEAD", http.StatusMethodNotAllowed) 499 500 _, err := tokens.Validate(&client, "abcdef12345") 501 if err == nil { 502 t.Errorf("Missing expected error from Validate") 503 } 504 } 505 506 func TestRevokeRequestSuccessful(t *testing.T) { 507 testhelper.SetupHTTP() 508 defer testhelper.TeardownHTTP() 509 client := prepareAuthTokenHandler(t, "DELETE", http.StatusNoContent) 510 511 res := tokens.Revoke(&client, "abcdef12345") 512 testhelper.AssertNoErr(t, res.Err) 513 } 514 515 func TestRevokeRequestError(t *testing.T) { 516 testhelper.SetupHTTP() 517 defer testhelper.TeardownHTTP() 518 client := prepareAuthTokenHandler(t, "DELETE", http.StatusNotFound) 519 520 res := tokens.Revoke(&client, "abcdef12345") 521 if res.Err == nil { 522 t.Errorf("Missing expected error from Revoke") 523 } 524 } 525 526 func TestNoTokenInResponse(t *testing.T) { 527 testhelper.SetupHTTP() 528 defer testhelper.TeardownHTTP() 529 530 client := golangsdk.ServiceClient{ 531 ProviderClient: &golangsdk.ProviderClient{}, 532 Endpoint: testhelper.Endpoint(), 533 } 534 535 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 536 w.WriteHeader(http.StatusCreated) 537 fmt.Fprintf(w, `{}`) 538 }) 539 540 options := tokens.AuthOptions{UserID: "me", Password: "squirrel!"} 541 _, err := tokens.Create(&client, &options).Extract() 542 testhelper.AssertNoErr(t, err) 543 }