github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/emswift/emswiftpkg/pkg_test.go (about) 1 // Copyright (c) 2015-2021, NVIDIA CORPORATION. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package emswiftpkg 5 6 import ( 7 "bytes" 8 "io" 9 "io/ioutil" 10 "net" 11 "net/http" 12 "strings" 13 "sync" 14 "testing" 15 16 "github.com/swiftstack/ProxyFS/conf" 17 "github.com/swiftstack/ProxyFS/utils" 18 ) 19 20 func TestAuthEmulation(t *testing.T) { 21 var ( 22 confMap conf.ConfMap 23 confStrings = []string{ 24 "EMSWIFT.AuthIPAddr=127.0.0.1", 25 "EMSWIFT.AuthTCPPort=9997", 26 "EMSWIFT.JRPCIPAddr=127.0.0.1", 27 "EMSWIFT.JRPCTCPPort=9998", 28 "EMSWIFT.NoAuthIPAddr=127.0.0.1", 29 "EMSWIFT.NoAuthTCPPort=9999", 30 "EMSWIFT.MaxAccountNameLength=256", 31 "EMSWIFT.MaxContainerNameLength=256", 32 "EMSWIFT.MaxObjectNameLength=1024", 33 "EMSWIFT.AccountListingLimit=10000", 34 "EMSWIFT.ContainerListingLimit=10000", 35 } 36 err error 37 expectedInfo string 38 expectedStorageURL string 39 httpClient *http.Client 40 httpRequest *http.Request 41 httpResponse *http.Response 42 readBuf []byte 43 testJRPCServerHandlerTCPListener *net.TCPListener 44 testJRPCServerHandlerWG *sync.WaitGroup 45 urlForAuth string 46 urlForInfo string 47 urlPrefix string 48 ) 49 50 confMap, err = conf.MakeConfMapFromStrings(confStrings) 51 if nil != err { 52 t.Fatalf("conf.MakeConfMapFromStrings(confStrings) returned unexpected error: %v", err) 53 } 54 55 err = Start(confMap) 56 if nil != err { 57 t.Fatalf("Start(confMap) returned unexpected error: %v", err) 58 } 59 60 testJRPCServerHandlerTCPListener, err = net.ListenTCP("tcp", globals.authEmulator.resolvedJRPCTCPAddr) 61 if nil != err { 62 t.Fatalf("net.ListenTCP() returned unexpected error: %v", err) 63 } 64 65 testJRPCServerHandlerWG = new(sync.WaitGroup) 66 testJRPCServerHandlerWG.Add(1) 67 go testJRPCServerHandler(testJRPCServerHandlerTCPListener, testJRPCServerHandlerWG) 68 69 // Format URLs 70 71 urlForInfo = "http://" + globals.authEmulator.httpServer.Addr + "/info" 72 urlForAuth = "http://" + globals.authEmulator.httpServer.Addr + "/auth/v1.0" 73 urlPrefix = "http://" + globals.authEmulator.httpServer.Addr + "/proxyfs/" 74 75 expectedStorageURL = "http://" + globals.authEmulator.httpServer.Addr + "/v1/" + "AUTH_test" 76 77 // Setup http.Client that we will use for all HTTP requests 78 79 httpClient = &http.Client{} 80 81 // Send a GET for "/info" expecting [EMSWIFT] data in compact JSON form 82 83 httpRequest, err = http.NewRequest("GET", urlForInfo, nil) 84 if nil != err { 85 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 86 } 87 httpResponse, err = httpClient.Do(httpRequest) 88 if nil != err { 89 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 90 } 91 if http.StatusOK != httpResponse.StatusCode { 92 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 93 } 94 expectedInfo = "{\"swift\": {\"max_account_name_length\": 256,\"max_container_name_length\": 256,\"max_object_name_length\": 1024,\"account_listing_limit\": 10000,\"container_listing_limit\": 10000}}" 95 if int64(len(expectedInfo)) != httpResponse.ContentLength { 96 t.Fatalf("GET of /info httpResponse.ContentLength unexpected") 97 } 98 readBuf, err = ioutil.ReadAll(httpResponse.Body) 99 if nil != err { 100 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 101 } 102 if expectedInfo != utils.ByteSliceToString(readBuf) { 103 t.Fatalf("GET of /info httpResponse.Body contents unexpected") 104 } 105 err = httpResponse.Body.Close() 106 if nil != err { 107 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 108 } 109 110 // Send a GET for "/auth/v1.0" expecting X-Auth-Token & X-Storage-Url 111 112 httpRequest, err = http.NewRequest("GET", urlForAuth, nil) 113 if nil != err { 114 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 115 } 116 httpRequest.Header.Add("X-Auth-User", "test:tester") 117 httpRequest.Header.Add("X-Auth-Key", "testing") 118 httpResponse, err = httpClient.Do(httpRequest) 119 if nil != err { 120 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 121 } 122 if http.StatusOK != httpResponse.StatusCode { 123 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 124 } 125 err = httpResponse.Body.Close() 126 if nil != err { 127 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 128 } 129 if httpResponse.Header.Get("X-Auth-Token") != fixedAuthToken { 130 t.Fatalf("Auth response should have header X-Auth-Token: %s", fixedAuthToken) 131 } 132 if httpResponse.Header.Get("X-Storage-Url") != expectedStorageURL { 133 t.Fatalf("Auth response should have header X-Storage-Url: %s", expectedStorageURL) 134 } 135 136 // Send a PUT for account "TestAccount" 137 138 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount", nil) 139 if nil != err { 140 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 141 } 142 httpRequest.Header.Add("X-Auth-Token", fixedAuthToken) 143 httpResponse, err = httpClient.Do(httpRequest) 144 if nil != err { 145 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 146 } 147 if http.StatusCreated != httpResponse.StatusCode { 148 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 149 } 150 err = httpResponse.Body.Close() 151 if nil != err { 152 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 153 } 154 155 // Send a GET for account "TestAccount" expecting Content-Length: 0 156 157 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount", nil) 158 if nil != err { 159 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 160 } 161 httpRequest.Header.Add("X-Auth-Token", fixedAuthToken) 162 httpResponse, err = httpClient.Do(httpRequest) 163 if nil != err { 164 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 165 } 166 if http.StatusNoContent != httpResponse.StatusCode { 167 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 168 } 169 if 0 != httpResponse.ContentLength { 170 t.Fatalf("TestAccount should contain no elements at this point") 171 } 172 err = httpResponse.Body.Close() 173 if nil != err { 174 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 175 } 176 177 // Send a PROXYFS JSON-RPC "request" that simply gets echo'd 178 179 httpRequest, err = http.NewRequest("PROXYFS", urlPrefix+"TestAccount", bytes.NewReader([]byte{'{', 'p', 'i', 'n', 'g', '}'})) 180 if nil != err { 181 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 182 } 183 httpRequest.Header.Add("X-Auth-Token", fixedAuthToken) 184 httpRequest.Header.Add("Content-Type", "application/json") 185 httpResponse, err = httpClient.Do(httpRequest) 186 if nil != err { 187 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 188 } 189 if http.StatusOK != httpResponse.StatusCode { 190 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 191 } 192 if httpResponse.Header.Get("Content-Type") != "application/json" { 193 t.Fatalf("TestAccount should have header Content-Type: application/json") 194 } 195 if int64(len("{ping}")) != httpResponse.ContentLength { 196 t.Fatalf("TestContainer should contain only \"{ping}\"") 197 } 198 readBuf, err = ioutil.ReadAll(httpResponse.Body) 199 if nil != err { 200 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 201 } 202 if "{ping}" != utils.ByteSliceToString(readBuf) { 203 t.Fatalf("TestContainer should contain only \"{ping}\"") 204 } 205 err = httpResponse.Body.Close() 206 if nil != err { 207 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 208 } 209 210 err = testJRPCServerHandlerTCPListener.Close() 211 if nil != err { 212 t.Fatalf("testJRPCServerHandlerTCPListener.Close() returned unexpected error: %v", err) 213 } 214 215 testJRPCServerHandlerWG.Wait() 216 217 err = Stop() 218 if nil != err { 219 t.Fatalf("Stop() returned unexpected error: %v", err) 220 } 221 } 222 223 func testJRPCServerHandler(testJRPCServerHandlerTCPListener *net.TCPListener, testJRPCServerHandlerWG *sync.WaitGroup) { 224 var ( 225 bytesWritten int 226 bytesWrittenInTotal int 227 err error 228 jrpcRequest []byte 229 jrpcRequestNestedLeftBraces uint32 230 jrpcRequestSingleByte []byte 231 jrpcResponse []byte 232 jrpcTCPConn *net.TCPConn 233 ) 234 235 DoAcceptTCP: 236 jrpcTCPConn, err = testJRPCServerHandlerTCPListener.AcceptTCP() 237 if nil != err { 238 testJRPCServerHandlerWG.Done() 239 return 240 } 241 242 jrpcRequest = make([]byte, 0) 243 jrpcRequestSingleByte = make([]byte, 1) 244 245 _, err = jrpcTCPConn.Read(jrpcRequestSingleByte) 246 if nil != err { 247 _ = jrpcTCPConn.Close() 248 goto DoAcceptTCP 249 } 250 jrpcRequest = append(jrpcRequest, jrpcRequestSingleByte[0]) 251 252 if '{' != jrpcRequestSingleByte[0] { 253 _ = jrpcTCPConn.Close() 254 goto DoAcceptTCP 255 } 256 257 jrpcRequestNestedLeftBraces = 1 258 259 for 0 < jrpcRequestNestedLeftBraces { 260 _, err = jrpcTCPConn.Read(jrpcRequestSingleByte) 261 if nil != err { 262 _ = jrpcTCPConn.Close() 263 goto DoAcceptTCP 264 } 265 jrpcRequest = append(jrpcRequest, jrpcRequestSingleByte[0]) 266 267 switch jrpcRequestSingleByte[0] { 268 case '{': 269 jrpcRequestNestedLeftBraces++ 270 case '}': 271 jrpcRequestNestedLeftBraces-- 272 default: 273 // Nothing special to do here 274 } 275 } 276 277 jrpcResponse = jrpcRequest 278 279 bytesWrittenInTotal = 0 280 281 for bytesWrittenInTotal < len(jrpcResponse) { 282 bytesWritten, err = jrpcTCPConn.Write(jrpcResponse[bytesWrittenInTotal:]) 283 if nil != err { 284 _ = jrpcTCPConn.Close() 285 goto DoAcceptTCP 286 } 287 bytesWrittenInTotal += bytesWritten 288 } 289 290 _ = jrpcTCPConn.Close() 291 goto DoAcceptTCP 292 } 293 294 func TestNoAuthEmulation(t *testing.T) { 295 var ( 296 confMap conf.ConfMap 297 confStrings = []string{ 298 "EMSWIFT.NoAuthIPAddr=127.0.0.1", 299 "EMSWIFT.NoAuthTCPPort=9999", 300 "EMSWIFT.MaxAccountNameLength=256", 301 "EMSWIFT.MaxContainerNameLength=256", 302 "EMSWIFT.MaxObjectNameLength=1024", 303 "EMSWIFT.AccountListingLimit=10000", 304 "EMSWIFT.ContainerListingLimit=10000", 305 } 306 contentType string 307 contentTypeMultiPartBoundary string 308 err error 309 errChan chan error 310 expectedBuf []byte 311 expectedInfo string 312 httpClient *http.Client 313 httpRequest *http.Request 314 httpResponse *http.Response 315 mouseHeaderPresent bool 316 pipeReader *io.PipeReader 317 pipeWriter *io.PipeWriter 318 readBuf []byte 319 urlForInfo string 320 urlPrefix string 321 ) 322 323 confMap, err = conf.MakeConfMapFromStrings(confStrings) 324 if nil != err { 325 t.Fatalf("conf.MakeConfMapFromStrings(confStrings) returned unexpected error: %v", err) 326 } 327 328 err = Start(confMap) 329 if nil != err { 330 t.Fatalf("Start(confMap) returned unexpected error: %v", err) 331 } 332 333 // Format URLs 334 335 urlForInfo = "http://" + globals.noAuthEmulator.httpServer.Addr + "/info" 336 urlPrefix = "http://" + globals.noAuthEmulator.httpServer.Addr + "/v1/" 337 338 // Setup http.Client that we will use for all HTTP requests 339 340 httpClient = &http.Client{} 341 342 // Send a GET for "/info" expecting [EMSWIFT] data in compact JSON form 343 344 httpRequest, err = http.NewRequest("GET", urlForInfo, nil) 345 if nil != err { 346 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 347 } 348 httpResponse, err = httpClient.Do(httpRequest) 349 if nil != err { 350 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 351 } 352 if http.StatusOK != httpResponse.StatusCode { 353 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 354 } 355 expectedInfo = "{\"swift\": {\"max_account_name_length\": 256,\"max_container_name_length\": 256,\"max_object_name_length\": 1024,\"account_listing_limit\": 10000,\"container_listing_limit\": 10000}}" 356 if int64(len(expectedInfo)) != httpResponse.ContentLength { 357 t.Fatalf("GET of /info httpResponse.ContentLength unexpected") 358 } 359 readBuf, err = ioutil.ReadAll(httpResponse.Body) 360 if nil != err { 361 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 362 } 363 if expectedInfo != utils.ByteSliceToString(readBuf) { 364 t.Fatalf("GET of /info httpResponse.Body contents unexpected") 365 } 366 err = httpResponse.Body.Close() 367 if nil != err { 368 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 369 } 370 371 // Send a PUT for account "TestAccount" and header Cat: Dog 372 373 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount", nil) 374 if nil != err { 375 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 376 } 377 httpRequest.Header.Add("Cat", "Dog") 378 httpResponse, err = httpClient.Do(httpRequest) 379 if nil != err { 380 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 381 } 382 if http.StatusCreated != httpResponse.StatusCode { 383 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 384 } 385 err = httpResponse.Body.Close() 386 if nil != err { 387 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 388 } 389 390 // Send a HEAD for account "TestAccount" expecting header Cat: Dog 391 392 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount", nil) 393 if nil != err { 394 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 395 } 396 httpResponse, err = httpClient.Do(httpRequest) 397 if nil != err { 398 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 399 } 400 if http.StatusNoContent != httpResponse.StatusCode { 401 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 402 } 403 if httpResponse.Header.Get("Cat") != "Dog" { 404 t.Fatalf("TestAccount should have header Cat: Dog") 405 } 406 err = httpResponse.Body.Close() 407 if nil != err { 408 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 409 } 410 411 // Send a GET for account "TestAccount" expecting Content-Length: 0 and header Cat: Dog 412 413 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount", nil) 414 if nil != err { 415 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 416 } 417 httpResponse, err = httpClient.Do(httpRequest) 418 if nil != err { 419 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 420 } 421 if http.StatusNoContent != httpResponse.StatusCode { 422 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 423 } 424 if httpResponse.Header.Get("Cat") != "Dog" { 425 t.Fatalf("TestAccount should have header Cat: Dog") 426 } 427 if 0 != httpResponse.ContentLength { 428 t.Fatalf("TestAccount should contain no elements at this point") 429 } 430 err = httpResponse.Body.Close() 431 if nil != err { 432 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 433 } 434 435 // Send a POST for account "TestAccount" and header Mouse: Bird 436 437 httpRequest, err = http.NewRequest("POST", urlPrefix+"TestAccount", nil) 438 if nil != err { 439 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 440 } 441 httpRequest.Header.Add("Mouse", "Bird") 442 httpResponse, err = httpClient.Do(httpRequest) 443 if nil != err { 444 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 445 } 446 if http.StatusNoContent != httpResponse.StatusCode { 447 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 448 } 449 err = httpResponse.Body.Close() 450 if nil != err { 451 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 452 } 453 454 // Send a HEAD for account "TestAccount" expecting header Cat: Dog & Mouse: Bird 455 456 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount", nil) 457 if nil != err { 458 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 459 } 460 httpResponse, err = httpClient.Do(httpRequest) 461 if nil != err { 462 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 463 } 464 if http.StatusNoContent != httpResponse.StatusCode { 465 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 466 } 467 if httpResponse.Header.Get("Cat") != "Dog" { 468 t.Fatalf("TestAccount should have header Cat: Dog") 469 } 470 if httpResponse.Header.Get("Mouse") != "Bird" { 471 t.Fatalf("TestAccount should have header Mouse: Bird") 472 } 473 err = httpResponse.Body.Close() 474 if nil != err { 475 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 476 } 477 478 // Send a POST for account "TestAccount" deleting header Mouse 479 480 httpRequest, err = http.NewRequest("POST", urlPrefix+"TestAccount", nil) 481 if nil != err { 482 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 483 } 484 httpRequest.Header.Add("Mouse", "") 485 httpResponse, err = httpClient.Do(httpRequest) 486 if nil != err { 487 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 488 } 489 if http.StatusNoContent != httpResponse.StatusCode { 490 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 491 } 492 err = httpResponse.Body.Close() 493 if nil != err { 494 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 495 } 496 497 // Send a HEAD for account "TestAccount" expecting header Cat: Dog & no Mouse header 498 499 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount", nil) 500 if nil != err { 501 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 502 } 503 httpResponse, err = httpClient.Do(httpRequest) 504 if nil != err { 505 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 506 } 507 if http.StatusNoContent != httpResponse.StatusCode { 508 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 509 } 510 if httpResponse.Header.Get("Cat") != "Dog" { 511 t.Fatalf("TestAccount should have header Cat: Dog") 512 } 513 _, mouseHeaderPresent = httpResponse.Header["Mouse"] 514 if mouseHeaderPresent { 515 t.Fatalf("TestAccount should not have header Mouse") 516 } 517 err = httpResponse.Body.Close() 518 if nil != err { 519 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 520 } 521 522 // Send a PUT for account "TestAccount" and header Mouse: Bird 523 524 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount", nil) 525 if nil != err { 526 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 527 } 528 httpRequest.Header.Add("Mouse", "Bird") 529 httpResponse, err = httpClient.Do(httpRequest) 530 if nil != err { 531 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 532 } 533 if http.StatusAccepted != httpResponse.StatusCode { 534 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 535 } 536 err = httpResponse.Body.Close() 537 if nil != err { 538 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 539 } 540 541 // Send a HEAD for account "TestAccount" expecting header Cat: Dog & Mouse: Bird 542 543 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount", nil) 544 if nil != err { 545 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 546 } 547 httpResponse, err = httpClient.Do(httpRequest) 548 if nil != err { 549 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 550 } 551 if http.StatusNoContent != httpResponse.StatusCode { 552 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 553 } 554 if httpResponse.Header.Get("Cat") != "Dog" { 555 t.Fatalf("TestAccount should have header Cat: Dog") 556 } 557 if httpResponse.Header.Get("Mouse") != "Bird" { 558 t.Fatalf("TestAccount should have header Mouse: Bird") 559 } 560 err = httpResponse.Body.Close() 561 if nil != err { 562 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 563 } 564 565 // Send a PUT for account "TestAccount" deleting header Mouse 566 567 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount", nil) 568 if nil != err { 569 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 570 } 571 httpRequest.Header.Add("Mouse", "") 572 httpResponse, err = httpClient.Do(httpRequest) 573 if nil != err { 574 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 575 } 576 if http.StatusAccepted != httpResponse.StatusCode { 577 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 578 } 579 err = httpResponse.Body.Close() 580 if nil != err { 581 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 582 } 583 584 // Send a HEAD for account "TestAccount" expecting header Cat: Dog & no Mouse header 585 586 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount", nil) 587 if nil != err { 588 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 589 } 590 httpResponse, err = httpClient.Do(httpRequest) 591 if nil != err { 592 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 593 } 594 if http.StatusNoContent != httpResponse.StatusCode { 595 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 596 } 597 if httpResponse.Header.Get("Cat") != "Dog" { 598 t.Fatalf("TestAccount should have header Cat: Dog") 599 } 600 _, mouseHeaderPresent = httpResponse.Header["Mouse"] 601 if mouseHeaderPresent { 602 t.Fatalf("TestAccount should not have header Mouse") 603 } 604 err = httpResponse.Body.Close() 605 if nil != err { 606 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 607 } 608 609 // Send a PUT for container "TestContainer" and header Cat: Dog 610 611 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount/TestContainer", nil) 612 if nil != err { 613 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 614 } 615 httpRequest.Header.Add("Cat", "Dog") 616 httpResponse, err = httpClient.Do(httpRequest) 617 if nil != err { 618 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 619 } 620 if http.StatusCreated != httpResponse.StatusCode { 621 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 622 } 623 err = httpResponse.Body.Close() 624 if nil != err { 625 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 626 } 627 628 // Send a GET for account "TestAccount" expecting "TestContainer\n" and header Cat: Dog 629 630 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount", nil) 631 if nil != err { 632 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 633 } 634 httpResponse, err = httpClient.Do(httpRequest) 635 if nil != err { 636 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 637 } 638 if http.StatusOK != httpResponse.StatusCode { 639 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 640 } 641 if httpResponse.Header.Get("Cat") != "Dog" { 642 t.Fatalf("TestAccount should have header Cat: Dog") 643 } 644 if int64(len("TestContainer\n")) != httpResponse.ContentLength { 645 t.Fatalf("TestAccount should contain only \"TestContainer\\n\" at this point") 646 } 647 readBuf, err = ioutil.ReadAll(httpResponse.Body) 648 if nil != err { 649 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 650 } 651 if "TestContainer\n" != utils.ByteSliceToString(readBuf) { 652 t.Fatalf("TestAccount should contain only \"TestContainer\\n\" at this point") 653 } 654 err = httpResponse.Body.Close() 655 if nil != err { 656 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 657 } 658 659 // Send a GET for account "TestAccount" with marker "AAA" expecting "TestContainer\n" and header Cat: Dog 660 661 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount?marker=AAA", nil) 662 if nil != err { 663 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 664 } 665 httpResponse, err = httpClient.Do(httpRequest) 666 if nil != err { 667 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 668 } 669 if http.StatusOK != httpResponse.StatusCode { 670 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 671 } 672 if httpResponse.Header.Get("Cat") != "Dog" { 673 t.Fatalf("TestAccount should have header Cat: Dog") 674 } 675 if int64(len("TestContainer\n")) != httpResponse.ContentLength { 676 t.Fatalf("TestAccount should contain only \"TestContainer\\n\" at this point") 677 } 678 readBuf, err = ioutil.ReadAll(httpResponse.Body) 679 if nil != err { 680 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 681 } 682 if "TestContainer\n" != utils.ByteSliceToString(readBuf) { 683 t.Fatalf("TestAccount should contain only \"TestContainer\\n\" at this point") 684 } 685 err = httpResponse.Body.Close() 686 if nil != err { 687 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 688 } 689 690 // Send a GET for account "TestAccount" with marker "ZZZ" expecting Content-Length: 0 and header Cat: Dog 691 692 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount?marker=ZZZ", nil) 693 if nil != err { 694 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 695 } 696 httpResponse, err = httpClient.Do(httpRequest) 697 if nil != err { 698 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 699 } 700 if http.StatusNoContent != httpResponse.StatusCode { 701 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 702 } 703 if httpResponse.Header.Get("Cat") != "Dog" { 704 t.Fatalf("TestAccount should have header Cat: Dog") 705 } 706 if 0 != httpResponse.ContentLength { 707 t.Fatalf("TestAccount should contain no elements at this point") 708 } 709 err = httpResponse.Body.Close() 710 if nil != err { 711 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 712 } 713 714 // Send a HEAD for container "TestContainer" expecting header Cat: Dog 715 716 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer", nil) 717 if nil != err { 718 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 719 } 720 httpResponse, err = httpClient.Do(httpRequest) 721 if nil != err { 722 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 723 } 724 if http.StatusNoContent != httpResponse.StatusCode { 725 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 726 } 727 if httpResponse.Header.Get("Cat") != "Dog" { 728 t.Fatalf("TestContainer should have header Cat: Dog") 729 } 730 err = httpResponse.Body.Close() 731 if nil != err { 732 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 733 } 734 735 // Send a GET for container "TestContainer" expecting Content-Length: 0 and header Cat: Dog 736 737 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount/TestContainer", nil) 738 if nil != err { 739 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 740 } 741 httpResponse, err = httpClient.Do(httpRequest) 742 if nil != err { 743 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 744 } 745 if http.StatusNoContent != httpResponse.StatusCode { 746 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 747 } 748 if httpResponse.Header.Get("Cat") != "Dog" { 749 t.Fatalf("TestContainer should have header Cat: Dog") 750 } 751 if 0 != httpResponse.ContentLength { 752 t.Fatalf("TestContainer should contain no elements at this point") 753 } 754 err = httpResponse.Body.Close() 755 if nil != err { 756 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 757 } 758 759 // Send a POST for container "TestContainer" and header Mouse: Bird 760 761 httpRequest, err = http.NewRequest("POST", urlPrefix+"TestAccount/TestContainer", nil) 762 if nil != err { 763 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 764 } 765 httpRequest.Header.Add("Mouse", "Bird") 766 httpResponse, err = httpClient.Do(httpRequest) 767 if nil != err { 768 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 769 } 770 if http.StatusNoContent != httpResponse.StatusCode { 771 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 772 } 773 err = httpResponse.Body.Close() 774 if nil != err { 775 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 776 } 777 778 // Send a HEAD for container "TestContainer" expecting header Cat: Dog & Mouse: Bird 779 780 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer", nil) 781 if nil != err { 782 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 783 } 784 httpResponse, err = httpClient.Do(httpRequest) 785 if nil != err { 786 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 787 } 788 if http.StatusNoContent != httpResponse.StatusCode { 789 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 790 } 791 if httpResponse.Header.Get("Cat") != "Dog" { 792 t.Fatalf("TestContainer should have header Cat: Dog") 793 } 794 if httpResponse.Header.Get("Mouse") != "Bird" { 795 t.Fatalf("TestContainer should have header Mouse: Bird") 796 } 797 err = httpResponse.Body.Close() 798 if nil != err { 799 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 800 } 801 802 // Send a POST for container "TestContainer" deleting header Mouse 803 804 httpRequest, err = http.NewRequest("POST", urlPrefix+"TestAccount/TestContainer", nil) 805 if nil != err { 806 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 807 } 808 httpRequest.Header.Add("Mouse", "") 809 httpResponse, err = httpClient.Do(httpRequest) 810 if nil != err { 811 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 812 } 813 if http.StatusNoContent != httpResponse.StatusCode { 814 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 815 } 816 err = httpResponse.Body.Close() 817 if nil != err { 818 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 819 } 820 821 // Send a HEAD for container "TestContainer" expecting header Cat: Dog & no Mouse header 822 823 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer", nil) 824 if nil != err { 825 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 826 } 827 httpResponse, err = httpClient.Do(httpRequest) 828 if nil != err { 829 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 830 } 831 if http.StatusNoContent != httpResponse.StatusCode { 832 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 833 } 834 if httpResponse.Header.Get("Cat") != "Dog" { 835 t.Fatalf("TestContainer should have header Cat: Dog") 836 } 837 _, mouseHeaderPresent = httpResponse.Header["Mouse"] 838 if mouseHeaderPresent { 839 t.Fatalf("TestContainer should not have header Mouse") 840 } 841 err = httpResponse.Body.Close() 842 if nil != err { 843 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 844 } 845 846 // Send a PUT for container "TestContainer" and header Mouse: Bird 847 848 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount/TestContainer", nil) 849 if nil != err { 850 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 851 } 852 httpRequest.Header.Add("Mouse", "Bird") 853 httpResponse, err = httpClient.Do(httpRequest) 854 if nil != err { 855 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 856 } 857 if http.StatusAccepted != httpResponse.StatusCode { 858 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 859 } 860 err = httpResponse.Body.Close() 861 if nil != err { 862 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 863 } 864 865 // Send a HEAD for container "TestContainer" expecting header Cat: Dog & Mouse: Bird 866 867 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer", nil) 868 if nil != err { 869 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 870 } 871 httpResponse, err = httpClient.Do(httpRequest) 872 if nil != err { 873 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 874 } 875 if http.StatusNoContent != httpResponse.StatusCode { 876 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 877 } 878 if httpResponse.Header.Get("Cat") != "Dog" { 879 t.Fatalf("TestContainer should have header Cat: Dog") 880 } 881 if httpResponse.Header.Get("Mouse") != "Bird" { 882 t.Fatalf("TestContainer should have header Mouse: Bird") 883 } 884 err = httpResponse.Body.Close() 885 if nil != err { 886 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 887 } 888 889 // Send a PUT for container "TestContainer" deleting header Mouse 890 891 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount/TestContainer", nil) 892 if nil != err { 893 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 894 } 895 httpRequest.Header.Add("Mouse", "") 896 httpResponse, err = httpClient.Do(httpRequest) 897 if nil != err { 898 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 899 } 900 if http.StatusAccepted != httpResponse.StatusCode { 901 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 902 } 903 err = httpResponse.Body.Close() 904 if nil != err { 905 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 906 } 907 908 // Send a HEAD for container "TestContainer" expecting header Cat: Dog & no Mouse header 909 910 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer", nil) 911 if nil != err { 912 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 913 } 914 httpResponse, err = httpClient.Do(httpRequest) 915 if nil != err { 916 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 917 } 918 if http.StatusNoContent != httpResponse.StatusCode { 919 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 920 } 921 if httpResponse.Header.Get("Cat") != "Dog" { 922 t.Fatalf("TestContainer should have header Cat: Dog") 923 } 924 _, mouseHeaderPresent = httpResponse.Header["Mouse"] 925 if mouseHeaderPresent { 926 t.Fatalf("TestContainer should not have header Mouse") 927 } 928 err = httpResponse.Body.Close() 929 if nil != err { 930 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 931 } 932 933 // Send a non-chunked PUT for object "Foo" to contain []byte{0x00, 0x01, 0x02} 934 935 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount/TestContainer/Foo", bytes.NewReader([]byte{0x00, 0x01, 0x02})) 936 if nil != err { 937 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 938 } 939 httpResponse, err = httpClient.Do(httpRequest) 940 if nil != err { 941 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 942 } 943 if http.StatusCreated != httpResponse.StatusCode { 944 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 945 } 946 err = httpResponse.Body.Close() 947 if nil != err { 948 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 949 } 950 951 // Send a chunked PUT for object "Bar"" with 1st chunk being []byte{0xAA, 0xBB} & 2nd chunk being []byte{0xCC, 0xDD, 0xEE} 952 953 pipeReader, pipeWriter = io.Pipe() 954 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount/TestContainer/Bar", pipeReader) 955 if nil != err { 956 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 957 } 958 httpRequest.ContentLength = -1 959 httpRequest.Header.Del("Content-Length") 960 errChan = make(chan error, 1) 961 go func() { 962 var ( 963 nonShadowingErr error 964 nonShadowingHTTPResponse *http.Response 965 ) 966 nonShadowingHTTPResponse, nonShadowingErr = httpClient.Do(httpRequest) 967 if nil == nonShadowingErr { 968 httpResponse = nonShadowingHTTPResponse 969 } 970 errChan <- nonShadowingErr 971 }() 972 _, err = pipeWriter.Write([]byte{0xAA, 0xBB}) 973 if nil != err { 974 t.Fatalf("pipeWriter.Write() returned unexpected error: %v", err) 975 } 976 _, err = pipeWriter.Write([]byte{0xCC, 0xDD, 0xEE}) 977 if nil != err { 978 t.Fatalf("pipeWriter.Write() returned unexpected error: %v", err) 979 } 980 err = pipeWriter.Close() 981 if nil != err { 982 t.Fatalf("pipeWriter.Close() returned unexpected error: %v", err) 983 } 984 err = <-errChan 985 if nil != err { 986 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 987 } 988 if http.StatusCreated != httpResponse.StatusCode { 989 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 990 } 991 err = httpResponse.Body.Close() 992 if nil != err { 993 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 994 } 995 996 // Send a GET for container "TestContainer" expecting "Bar\nFoo\n" and header Cat: Dog 997 998 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount/TestContainer", nil) 999 if nil != err { 1000 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1001 } 1002 httpResponse, err = httpClient.Do(httpRequest) 1003 if nil != err { 1004 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1005 } 1006 if http.StatusOK != httpResponse.StatusCode { 1007 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1008 } 1009 if httpResponse.Header.Get("Cat") != "Dog" { 1010 t.Fatalf("TestAccount should have header Cat: Dog") 1011 } 1012 if int64(len("Bar\nFoo\n")) != httpResponse.ContentLength { 1013 t.Fatalf("TestContainer should contain only \"Bar\\nFoo\\n\" at this point") 1014 } 1015 readBuf, err = ioutil.ReadAll(httpResponse.Body) 1016 if nil != err { 1017 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 1018 } 1019 if "Bar\nFoo\n" != utils.ByteSliceToString(readBuf) { 1020 t.Fatalf("TestContainer should contain only \"Bar\\nFoo\\n\" at this point") 1021 } 1022 err = httpResponse.Body.Close() 1023 if nil != err { 1024 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1025 } 1026 1027 // Send a GET for container "TestContainer" with marker "AAA" expecting "Bar\nFoo\n" and header Cat: Dog 1028 1029 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount/TestContainer?marker=AAA", nil) 1030 if nil != err { 1031 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1032 } 1033 httpResponse, err = httpClient.Do(httpRequest) 1034 if nil != err { 1035 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1036 } 1037 if http.StatusOK != httpResponse.StatusCode { 1038 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1039 } 1040 if httpResponse.Header.Get("Cat") != "Dog" { 1041 t.Fatalf("TestAccount should have header Cat: Dog") 1042 } 1043 if int64(len("Bar\nFoo\n")) != httpResponse.ContentLength { 1044 t.Fatalf("TestContainer should contain only \"Bar\\nFoo\\n\" at this point") 1045 } 1046 readBuf, err = ioutil.ReadAll(httpResponse.Body) 1047 if nil != err { 1048 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 1049 } 1050 if "Bar\nFoo\n" != utils.ByteSliceToString(readBuf) { 1051 t.Fatalf("TestContainer should contain only \"Bar\\nFoo\\n\" at this point") 1052 } 1053 err = httpResponse.Body.Close() 1054 if nil != err { 1055 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1056 } 1057 1058 // Send a GET for container "TestContainer" with marker "ZZZ" expecting Content-Length: 0 and header Cat: Dog 1059 1060 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount/TestContainer?marker=ZZZ", nil) 1061 if nil != err { 1062 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1063 } 1064 httpResponse, err = httpClient.Do(httpRequest) 1065 if nil != err { 1066 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1067 } 1068 if http.StatusNoContent != httpResponse.StatusCode { 1069 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1070 } 1071 if httpResponse.Header.Get("Cat") != "Dog" { 1072 t.Fatalf("TestContainer should have header Cat: Dog") 1073 } 1074 if 0 != httpResponse.ContentLength { 1075 t.Fatalf("TestContainer should contain no elements at this point") 1076 } 1077 err = httpResponse.Body.Close() 1078 if nil != err { 1079 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1080 } 1081 1082 // Send a HEAD for object "Foo" expecting Content-Length: 3 1083 1084 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer/Foo", nil) 1085 if nil != err { 1086 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1087 } 1088 httpResponse, err = httpClient.Do(httpRequest) 1089 if nil != err { 1090 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1091 } 1092 if http.StatusOK != httpResponse.StatusCode { 1093 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1094 } 1095 if 3 != httpResponse.ContentLength { 1096 t.Fatalf("httpResponse.ContentLength contained unexpected value: %v", httpResponse.ContentLength) 1097 } 1098 err = httpResponse.Body.Close() 1099 if nil != err { 1100 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1101 } 1102 1103 // Send a full object GET for object "Foo" expecting []byte{0x00, 0x01, 0x02} 1104 1105 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount/TestContainer/Foo", nil) 1106 if nil != err { 1107 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1108 } 1109 httpResponse, err = httpClient.Do(httpRequest) 1110 if nil != err { 1111 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1112 } 1113 if http.StatusOK != httpResponse.StatusCode { 1114 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1115 } 1116 if int64(len([]byte{0x00, 0x01, 0x02})) != httpResponse.ContentLength { 1117 t.Fatalf("Foo should contain precisely []byte{0x00, 0x01, 0x02}") 1118 } 1119 readBuf, err = ioutil.ReadAll(httpResponse.Body) 1120 if nil != err { 1121 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 1122 } 1123 if 0 != bytes.Compare([]byte{0x00, 0x01, 0x02}, readBuf) { 1124 t.Fatalf("Foo should contain precisely []byte{0x00, 0x01, 0x02}") 1125 } 1126 err = httpResponse.Body.Close() 1127 if nil != err { 1128 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1129 } 1130 1131 // Send a range GET of bytes at offset 1 for length 3 for object "Bar" expecting []byte{0xBB, 0xCC, 0xDD} 1132 1133 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount/TestContainer/Bar", nil) 1134 if nil != err { 1135 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1136 } 1137 httpRequest.Header.Add("Range", "bytes=1-3") 1138 httpResponse, err = httpClient.Do(httpRequest) 1139 if nil != err { 1140 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1141 } 1142 if http.StatusPartialContent != httpResponse.StatusCode { 1143 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1144 } 1145 if int64(len([]byte{0xBB, 0xCC, 0xDD})) != httpResponse.ContentLength { 1146 t.Fatalf("Bar's bytes 1-3 should contain precisely []byte{0xBB, 0xCC, 0xDD}") 1147 } 1148 readBuf, err = ioutil.ReadAll(httpResponse.Body) 1149 if nil != err { 1150 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 1151 } 1152 if 0 != bytes.Compare([]byte{0xBB, 0xCC, 0xDD}, readBuf) { 1153 t.Fatalf("Bar's bytes 1-3 should contain precisely []byte{0xBB, 0xCC, 0xDD}") 1154 } 1155 err = httpResponse.Body.Close() 1156 if nil != err { 1157 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1158 } 1159 1160 // Send a range GET of bytes at offset 0 for length 2 1161 // and offset 3 for length of 1 for object "Bar" 1162 // expecting two MIME parts: []byte{0xAA, 0xBB} and []byte{0xDD} 1163 1164 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount/TestContainer/Bar", nil) 1165 if nil != err { 1166 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1167 } 1168 httpRequest.Header.Add("Range", "bytes=0-1,3-3") 1169 httpResponse, err = httpClient.Do(httpRequest) 1170 if nil != err { 1171 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1172 } 1173 if http.StatusPartialContent != httpResponse.StatusCode { 1174 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1175 } 1176 contentType = httpResponse.Header.Get("Content-Type") 1177 contentTypeMultiPartBoundary = strings.TrimPrefix(contentType, "multipart/byteranges; boundary=") 1178 if (len(contentType) == len(contentTypeMultiPartBoundary)) || (0 == len(contentTypeMultiPartBoundary)) { 1179 t.Fatalf("httpReponse.Header[\"Content-Type\"] contained unexpected value: \"%v\"", contentType) 1180 } 1181 expectedBuf = make([]byte, 0, httpResponse.ContentLength) 1182 expectedBuf = append(expectedBuf, []byte("--"+contentTypeMultiPartBoundary+"\r\n")...) 1183 expectedBuf = append(expectedBuf, []byte("Content-Type: application/octet-stream\r\n")...) 1184 expectedBuf = append(expectedBuf, []byte("Content-Range: bytes 0-1/5\r\n")...) 1185 expectedBuf = append(expectedBuf, []byte("\r\n")...) 1186 expectedBuf = append(expectedBuf, []byte{0xAA, 0xBB}...) 1187 expectedBuf = append(expectedBuf, []byte("\r\n")...) 1188 expectedBuf = append(expectedBuf, []byte("--"+contentTypeMultiPartBoundary+"\r\n")...) 1189 expectedBuf = append(expectedBuf, []byte("Content-Type: application/octet-stream\r\n")...) 1190 expectedBuf = append(expectedBuf, []byte("Content-Range: bytes 3-3/5\r\n")...) 1191 expectedBuf = append(expectedBuf, []byte("\r\n")...) 1192 expectedBuf = append(expectedBuf, []byte{0xDD}...) 1193 expectedBuf = append(expectedBuf, []byte("\r\n")...) 1194 expectedBuf = append(expectedBuf, []byte("--"+contentTypeMultiPartBoundary+"--")...) 1195 if int64(len(expectedBuf)) != httpResponse.ContentLength { 1196 t.Fatalf("Unexpected multi-part GET response Content-Length") 1197 } 1198 readBuf, err = ioutil.ReadAll(httpResponse.Body) 1199 if nil != err { 1200 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 1201 } 1202 if 0 != bytes.Compare(expectedBuf, readBuf) { 1203 t.Fatalf("Unexpected payload of multi-part GET response") 1204 } 1205 err = httpResponse.Body.Close() 1206 if nil != err { 1207 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1208 } 1209 1210 // Send a tail GET of the last 2 bytes for object "Bar" expecting []byte{0xDD, 0xEE} 1211 1212 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount/TestContainer/Bar", nil) 1213 if nil != err { 1214 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1215 } 1216 httpRequest.Header.Add("Range", "bytes=-2") 1217 httpResponse, err = httpClient.Do(httpRequest) 1218 if nil != err { 1219 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1220 } 1221 if http.StatusPartialContent != httpResponse.StatusCode { 1222 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1223 } 1224 if int64(len([]byte{0xDD, 0xEE})) != httpResponse.ContentLength { 1225 t.Fatalf("Bar's last 2 bytes should contain precisely []byte{0xDD, 0xEE}") 1226 } 1227 readBuf, err = ioutil.ReadAll(httpResponse.Body) 1228 if nil != err { 1229 t.Fatalf("ioutil.ReadAll() returned unexpected error: %v", err) 1230 } 1231 if 0 != bytes.Compare([]byte{0xDD, 0xEE}, readBuf) { 1232 t.Fatalf("Bar's last 2 bytes should contain precisely []byte{0xDD, 0xEE}") 1233 } 1234 err = httpResponse.Body.Close() 1235 if nil != err { 1236 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1237 } 1238 1239 // Send a PUT for object "ZigZag" and header Cat: Dog 1240 1241 httpRequest, err = http.NewRequest("PUT", urlPrefix+"TestAccount/TestContainer/ZigZag", nil) 1242 if nil != err { 1243 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1244 } 1245 httpRequest.Header.Add("Cat", "Dog") 1246 httpResponse, err = httpClient.Do(httpRequest) 1247 if nil != err { 1248 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1249 } 1250 if http.StatusCreated != httpResponse.StatusCode { 1251 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1252 } 1253 err = httpResponse.Body.Close() 1254 if nil != err { 1255 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1256 } 1257 1258 // Send a HEAD for object "ZigZag" expecting header Cat: Dog 1259 1260 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer/ZigZag", nil) 1261 if nil != err { 1262 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1263 } 1264 httpResponse, err = httpClient.Do(httpRequest) 1265 if nil != err { 1266 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1267 } 1268 if http.StatusOK != httpResponse.StatusCode { 1269 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1270 } 1271 if httpResponse.Header.Get("Cat") != "Dog" { 1272 t.Fatalf("TestAccount should have header Cat: Dog") 1273 } 1274 err = httpResponse.Body.Close() 1275 if nil != err { 1276 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1277 } 1278 1279 // Send a HEAD for object "ZigZag" expecting header Cat: Dog 1280 1281 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer/ZigZag", nil) 1282 if nil != err { 1283 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1284 } 1285 httpResponse, err = httpClient.Do(httpRequest) 1286 if nil != err { 1287 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1288 } 1289 if http.StatusOK != httpResponse.StatusCode { 1290 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1291 } 1292 if httpResponse.Header.Get("Cat") != "Dog" { 1293 t.Fatalf("TestAccount should have header Cat: Dog") 1294 } 1295 err = httpResponse.Body.Close() 1296 if nil != err { 1297 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1298 } 1299 1300 // Send a POST for object "ZigZag" and header Mouse: Bird 1301 1302 httpRequest, err = http.NewRequest("POST", urlPrefix+"TestAccount/TestContainer/ZigZag", nil) 1303 if nil != err { 1304 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1305 } 1306 httpRequest.Header.Add("Mouse", "Bird") 1307 httpResponse, err = httpClient.Do(httpRequest) 1308 if nil != err { 1309 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1310 } 1311 if http.StatusNoContent != httpResponse.StatusCode { 1312 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1313 } 1314 err = httpResponse.Body.Close() 1315 if nil != err { 1316 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1317 } 1318 1319 // Send a HEAD for object "ZigZag" expecting header Cat: Dog & Mouse: Bird 1320 1321 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer/ZigZag", nil) 1322 if nil != err { 1323 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1324 } 1325 httpResponse, err = httpClient.Do(httpRequest) 1326 if nil != err { 1327 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1328 } 1329 if http.StatusOK != httpResponse.StatusCode { 1330 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1331 } 1332 if httpResponse.Header.Get("Cat") != "Dog" { 1333 t.Fatalf("TestAccount should have header Cat: Dog") 1334 } 1335 if httpResponse.Header.Get("Mouse") != "Bird" { 1336 t.Fatalf("TestAccount should have header Mouse: Bird") 1337 } 1338 err = httpResponse.Body.Close() 1339 if nil != err { 1340 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1341 } 1342 1343 // Send a POST for object "ZigZag" deleting header Mouse 1344 1345 httpRequest, err = http.NewRequest("POST", urlPrefix+"TestAccount/TestContainer/ZigZag", nil) 1346 if nil != err { 1347 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1348 } 1349 httpRequest.Header.Add("Mouse", "") 1350 httpResponse, err = httpClient.Do(httpRequest) 1351 if nil != err { 1352 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1353 } 1354 if http.StatusNoContent != httpResponse.StatusCode { 1355 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1356 } 1357 err = httpResponse.Body.Close() 1358 if nil != err { 1359 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1360 } 1361 1362 // Send a HEAD for object "ZigZag" expecting header Cat: Dog & no Mouse header 1363 1364 httpRequest, err = http.NewRequest("HEAD", urlPrefix+"TestAccount/TestContainer/ZigZag", nil) 1365 if nil != err { 1366 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1367 } 1368 httpResponse, err = httpClient.Do(httpRequest) 1369 if nil != err { 1370 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1371 } 1372 if http.StatusOK != httpResponse.StatusCode { 1373 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1374 } 1375 if httpResponse.Header.Get("Cat") != "Dog" { 1376 t.Fatalf("TestAccount should have header Cat: Dog") 1377 } 1378 _, mouseHeaderPresent = httpResponse.Header["Mouse"] 1379 if mouseHeaderPresent { 1380 t.Fatalf("TestAccount should not have header Mouse") 1381 } 1382 err = httpResponse.Body.Close() 1383 if nil != err { 1384 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1385 } 1386 1387 // Send a DELETE for object "Foo" 1388 1389 httpRequest, err = http.NewRequest("DELETE", urlPrefix+"TestAccount/TestContainer/Foo", nil) 1390 if nil != err { 1391 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1392 } 1393 httpResponse, err = httpClient.Do(httpRequest) 1394 if nil != err { 1395 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1396 } 1397 if http.StatusNoContent != httpResponse.StatusCode { 1398 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1399 } 1400 err = httpResponse.Body.Close() 1401 if nil != err { 1402 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1403 } 1404 1405 // Send a DELETE for object "Bar" 1406 1407 httpRequest, err = http.NewRequest("DELETE", urlPrefix+"TestAccount/TestContainer/Bar", nil) 1408 if nil != err { 1409 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1410 } 1411 httpResponse, err = httpClient.Do(httpRequest) 1412 if nil != err { 1413 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1414 } 1415 if http.StatusNoContent != httpResponse.StatusCode { 1416 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1417 } 1418 err = httpResponse.Body.Close() 1419 if nil != err { 1420 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1421 } 1422 1423 // Send a DELETE for object "ZigZag" 1424 1425 httpRequest, err = http.NewRequest("DELETE", urlPrefix+"TestAccount/TestContainer/ZigZag", nil) 1426 if nil != err { 1427 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1428 } 1429 httpResponse, err = httpClient.Do(httpRequest) 1430 if nil != err { 1431 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1432 } 1433 if http.StatusNoContent != httpResponse.StatusCode { 1434 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1435 } 1436 err = httpResponse.Body.Close() 1437 if nil != err { 1438 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1439 } 1440 1441 // Send a GET for container "TestContainer" expecting Content-Length: 0 and header Cat: Dog 1442 1443 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount/TestContainer", nil) 1444 if nil != err { 1445 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1446 } 1447 httpResponse, err = httpClient.Do(httpRequest) 1448 if nil != err { 1449 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1450 } 1451 if http.StatusNoContent != httpResponse.StatusCode { 1452 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1453 } 1454 if httpResponse.Header.Get("Cat") != "Dog" { 1455 t.Fatalf("TestContainer should have header Cat: Dog") 1456 } 1457 if 0 != httpResponse.ContentLength { 1458 t.Fatalf("TestContainer should contain no elements at this point") 1459 } 1460 err = httpResponse.Body.Close() 1461 if nil != err { 1462 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1463 } 1464 1465 // Send a DELETE for container "TestContainer" 1466 1467 httpRequest, err = http.NewRequest("DELETE", urlPrefix+"TestAccount/TestContainer", nil) 1468 if nil != err { 1469 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1470 } 1471 httpResponse, err = httpClient.Do(httpRequest) 1472 if nil != err { 1473 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1474 } 1475 if http.StatusNoContent != httpResponse.StatusCode { 1476 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1477 } 1478 err = httpResponse.Body.Close() 1479 if nil != err { 1480 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1481 } 1482 1483 // Send a GET for account "TestAccount" expecting Content-Length: 0 and header Cat: Dog 1484 1485 httpRequest, err = http.NewRequest("GET", urlPrefix+"TestAccount", nil) 1486 if nil != err { 1487 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1488 } 1489 httpResponse, err = httpClient.Do(httpRequest) 1490 if nil != err { 1491 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1492 } 1493 if http.StatusNoContent != httpResponse.StatusCode { 1494 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1495 } 1496 if httpResponse.Header.Get("Cat") != "Dog" { 1497 t.Fatalf("TestAccount should have header Cat: Dog") 1498 } 1499 if 0 != httpResponse.ContentLength { 1500 t.Fatalf("TestAccount should contain no elements at this point") 1501 } 1502 err = httpResponse.Body.Close() 1503 if nil != err { 1504 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1505 } 1506 1507 // Send a DELETE for account "TestAccount" 1508 1509 httpRequest, err = http.NewRequest("DELETE", urlPrefix+"TestAccount", nil) 1510 if nil != err { 1511 t.Fatalf("http.NewRequest() returned unexpected error: %v", err) 1512 } 1513 httpResponse, err = httpClient.Do(httpRequest) 1514 if nil != err { 1515 t.Fatalf("httpClient.Do() returned unexpected error: %v", err) 1516 } 1517 if http.StatusNoContent != httpResponse.StatusCode { 1518 t.Fatalf("httpResponse.StatusCode contained unexpected value: %v", httpResponse.StatusCode) 1519 } 1520 err = httpResponse.Body.Close() 1521 if nil != err { 1522 t.Fatalf("http.Response.Body.Close() returned unexpected error: %v", err) 1523 } 1524 1525 err = Stop() 1526 if nil != err { 1527 t.Fatalf("Stop() returned unexpected error: %v", err) 1528 } 1529 }