github.com/rohankumardubey/proxyfs@v0.0.0-20210108201508-653efa9ab00e/statslogger/config_test.go (about) 1 package statslogger 2 3 /* 4 * Test the statistics logger. 5 * 6 * Most of this file is copied from swiftclient/api_test.go because we want to 7 * perform some swift client operations where we can look at the updated 8 * statistics. 9 */ 10 11 import ( 12 "bytes" 13 "errors" 14 "fmt" 15 "math/rand" 16 "sync" 17 "testing" 18 "time" 19 20 "golang.org/x/sys/unix" 21 22 "github.com/swiftstack/ProxyFS/conf" 23 "github.com/swiftstack/ProxyFS/ramswift" 24 "github.com/swiftstack/ProxyFS/swiftclient" 25 "github.com/swiftstack/ProxyFS/transitions" 26 ) 27 28 func (tOCCS *testObjectCopyCallbackStruct) BytesRemaining(bytesRemaining uint64) (chunkSize uint64) { 29 chunkSize = tOCCS.chunkSize 30 return 31 } 32 33 type testObjectCopyCallbackStruct struct { 34 srcAccountName string 35 srcContainerName string 36 srcObjectName string 37 dstAccountName string 38 dstContainerName string 39 dstObjectName string 40 chunkSize uint64 41 } 42 43 func TestAPI(t *testing.T) { 44 var ( 45 confMap conf.ConfMap 46 confStrings []string 47 err error 48 signalHandlerIsArmedWG sync.WaitGroup 49 ) 50 51 confStrings = []string{ 52 "Stats.IPAddr=localhost", 53 "Stats.UDPPort=52184", 54 "Stats.BufferLength=100", 55 "Stats.MaxLatency=1s", 56 57 "StatsLogger.Period=0m", 58 "StatsLogger.Verbose=false", 59 60 "SwiftClient.NoAuthIPAddr=127.0.0.1", 61 "SwiftClient.NoAuthTCPPort=9999", 62 "SwiftClient.Timeout=10s", 63 "SwiftClient.RetryLimit=5", 64 "SwiftClient.RetryLimitObject=5", 65 "SwiftClient.RetryDelay=250ms", 66 "SwiftClient.RetryDelayObject=250ms", 67 "SwiftClient.RetryExpBackoff=1.2", 68 "SwiftClient.RetryExpBackoffObject=2.0", 69 "SwiftClient.ChunkedConnectionPoolSize=64", 70 "SwiftClient.NonChunkedConnectionPoolSize=32", 71 72 "Cluster.WhoAmI=Peer0", 73 74 "Peer:Peer0.ReadCacheQuotaFraction=0.20", 75 76 "FSGlobals.VolumeGroupList=", 77 "FSGlobals.CheckpointHeaderConsensusAttempts=5", 78 "FSGlobals.MountRetryLimit=6", 79 "FSGlobals.MountRetryDelay=1s", 80 "FSGlobals.MountRetryExpBackoff=2", 81 "FSGlobals.LogCheckpointHeaderPosts=true", 82 "FSGlobals.TryLockBackoffMin=10ms", 83 "FSGlobals.TryLockBackoffMax=50ms", 84 "FSGlobals.TryLockSerializationThreshhold=5", 85 "FSGlobals.SymlinkMax=32", 86 "FSGlobals.CoalesceElementChunkSize=16", 87 "FSGlobals.EtcdEnabled=false", 88 89 "RamSwiftInfo.MaxAccountNameLength=256", 90 "RamSwiftInfo.MaxContainerNameLength=256", 91 "RamSwiftInfo.MaxObjectNameLength=1024", 92 "RamSwiftInfo.AccountListingLimit=10000", 93 "RamSwiftInfo.ContainerListingLimit=10000", 94 } 95 96 confMap, err = conf.MakeConfMapFromStrings(confStrings) 97 if err != nil { 98 t.Fatalf("%v", err) 99 } 100 101 signalHandlerIsArmedWG.Add(1) 102 doneChan := make(chan bool, 1) // Must be buffered to avoid race 103 104 go ramswift.Daemon("/dev/null", confStrings, &signalHandlerIsArmedWG, doneChan, unix.SIGTERM) 105 106 signalHandlerIsArmedWG.Wait() 107 108 err = transitions.Up(confMap) 109 if nil != err { 110 t.Fatalf("transitions.Up(confMap) failed: %v", err) 111 } 112 113 if globals.statsLogPeriod != 0 { 114 t.Fatalf("after Up('StatsLogger.Period=0s') globals.statsLogPeriod != 0") 115 } 116 117 err = confMap.UpdateFromString("StatsLogger.Period=1s") 118 if nil != err { 119 t.Fatalf("UpdateFromString('StatsLogger.Period=1s') failed: %v", err) 120 } 121 122 err = transitions.Signaled(confMap) 123 if nil != err { 124 t.Fatalf("transitions.Signaled(confMap) failed: %v", err) 125 } 126 127 if globals.statsLogPeriod != 1*time.Second { 128 t.Fatalf("after Signaled('StatsLogger.Period=1s') globals.statsLogPeriod != 1 sec") 129 } 130 131 // Run the tests 132 // 133 // "Real" unit tests would verify the information written into the log 134 // 135 // t.Run("testRetry", testRetry) 136 // t.Run("testOps", testOps) 137 testOps(t) 138 testChunkedPut(t) 139 testReload(t, confMap) 140 141 // Shutdown packages 142 143 err = transitions.Down(confMap) 144 if nil != err { 145 t.Fatalf("transitions.Down(confMap) failed: %v", err) 146 } 147 148 // Send ourself a SIGTERM to terminate ramswift.Daemon() 149 150 unix.Kill(unix.Getpid(), unix.SIGTERM) 151 152 _ = <-doneChan 153 } 154 155 // Test normal Swift client operations so we have something in the log 156 // 157 func testOps(t *testing.T) { 158 // headers for testing 159 160 catDogHeaderMap := make(map[string][]string) 161 catDogHeaderMap["Cat"] = []string{"Dog"} 162 163 mouseBirdHeaderMap := make(map[string][]string) 164 mouseBirdHeaderMap["Mouse"] = []string{"Bird"} 165 166 mouseDeleteHeaderMap := make(map[string][]string) 167 mouseDeleteHeaderMap["Mouse"] = []string{""} 168 169 // Send a PUT for account "TestAccount" and header Cat: Dog 170 171 err := swiftclient.AccountPut("TestAccount", catDogHeaderMap) 172 if nil != err { 173 tErr := fmt.Sprintf("AccountPut(\"TestAccount\", catDogHeaderMap) failed: %v", err) 174 t.Fatalf(tErr) 175 } 176 177 // Send a HEAD for account "TestAccount" expecting header Cat: Dog 178 179 accountHeaders, err := swiftclient.AccountHead("TestAccount") 180 if nil != err { 181 tErr := fmt.Sprintf("AccountHead(\"TestAccount\") failed: %v", err) 182 t.Fatalf(tErr) 183 } 184 accountCatHeader, ok := accountHeaders["Cat"] 185 if !ok { 186 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\"") 187 } 188 if (1 != len(accountCatHeader)) || ("Dog" != accountCatHeader[0]) { 189 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 190 } 191 192 // Send a GET for account "TestAccount" expecting header Cat: Dog and containerList []string{} 193 194 accountHeaders, containerList, err := swiftclient.AccountGet("TestAccount") 195 if nil != err { 196 tErr := fmt.Sprintf("AccountGet(\"TestAccount\") failed: %v", err) 197 t.Fatalf(tErr) 198 } 199 accountCatHeader, ok = accountHeaders["Cat"] 200 if !ok { 201 t.Fatalf("AccountGet(\"TestAccount\") didn't return Header \"Cat\"") 202 } 203 if (1 != len(accountCatHeader)) || ("Dog" != accountCatHeader[0]) { 204 t.Fatalf("AccountGet(\"TestAccount\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 205 } 206 if 0 != len(containerList) { 207 t.Fatalf("AccountGet(\"TestAccount\") didn't return expected containerList") 208 } 209 210 // Send a POST for account "TestAccount" adding header Mouse: Bird 211 212 err = swiftclient.AccountPost("TestAccount", mouseBirdHeaderMap) 213 if nil != err { 214 tErr := fmt.Sprintf("AccountPost(\"TestAccount\", mouseBirdHeaderMap) failed: %v", err) 215 t.Fatalf(tErr) 216 } 217 218 // Send a HEAD for account "TestAccount" expecting header Cat: Dog & Mouse: Bird 219 220 accountHeaders, err = swiftclient.AccountHead("TestAccount") 221 if nil != err { 222 tErr := fmt.Sprintf("AccountHead(\"TestAccount\") failed: %v", err) 223 t.Fatalf(tErr) 224 } 225 accountCatHeader, ok = accountHeaders["Cat"] 226 if !ok { 227 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\"") 228 } 229 if (1 != len(accountCatHeader)) || ("Dog" != accountCatHeader[0]) { 230 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 231 } 232 mouseBirdHeader, ok := accountHeaders["Mouse"] 233 if !ok { 234 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Mouse\"") 235 } 236 if (1 != len(mouseBirdHeader)) || ("Bird" != mouseBirdHeader[0]) { 237 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Bird\" having value []string{\"Mouse\"}") 238 } 239 240 // Send a POST for account "TestAccount" deleting header Mouse 241 242 err = swiftclient.AccountPost("TestAccount", mouseDeleteHeaderMap) 243 if nil != err { 244 tErr := fmt.Sprintf("AccountPost(\"TestAccount\", mouseDeleteHeaderMap) failed: %v", err) 245 t.Fatalf(tErr) 246 } 247 248 // Send a HEAD for account "TestAccount" expecting header Cat: Dog & no Mouse header 249 250 accountHeaders, err = swiftclient.AccountHead("TestAccount") 251 if nil != err { 252 tErr := fmt.Sprintf("AccountHead(\"TestAccount\") failed: %v", err) 253 t.Fatalf(tErr) 254 } 255 accountCatHeader, ok = accountHeaders["Cat"] 256 if !ok { 257 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\"") 258 } 259 if (1 != len(accountCatHeader)) || ("Dog" != accountCatHeader[0]) { 260 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 261 } 262 _, ok = accountHeaders["Mouse"] 263 if ok { 264 t.Fatalf("AccountHead(\"TestAccount\") shouldn't have returned Header \"Mouse\"") 265 } 266 267 // Send a PUT for account "TestAccount" adding header Mouse: Bird 268 269 err = swiftclient.AccountPut("TestAccount", mouseBirdHeaderMap) 270 if nil != err { 271 tErr := fmt.Sprintf("AccountPut(\"TestAccount\", mouseBirdHeaderMap) failed: %v", err) 272 t.Fatalf(tErr) 273 } 274 275 // Send a HEAD for account "TestAccount" expecting header Cat: Dog & Mouse: Bird 276 277 accountHeaders, err = swiftclient.AccountHead("TestAccount") 278 if nil != err { 279 tErr := fmt.Sprintf("AccountHead(\"TestAccount\") failed: %v", err) 280 t.Fatalf(tErr) 281 } 282 accountCatHeader, ok = accountHeaders["Cat"] 283 if !ok { 284 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\"") 285 } 286 if (1 != len(accountCatHeader)) || ("Dog" != accountCatHeader[0]) { 287 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 288 } 289 mouseBirdHeader, ok = accountHeaders["Mouse"] 290 if !ok { 291 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Mouse\"") 292 } 293 if (1 != len(mouseBirdHeader)) || ("Bird" != mouseBirdHeader[0]) { 294 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Bird\" having value []string{\"Mouse\"}") 295 } 296 297 // Send a PUT for account "TestAccount" deleting header Mouse 298 299 err = swiftclient.AccountPut("TestAccount", mouseDeleteHeaderMap) 300 if nil != err { 301 tErr := fmt.Sprintf("AccountPut(\"TestAccount\", mouseDeleteHeaderMap) failed: %v", err) 302 t.Fatalf(tErr) 303 } 304 305 // Send a HEAD for account "TestAccount" expecting header Cat: Dog & no Mouse header 306 307 accountHeaders, err = swiftclient.AccountHead("TestAccount") 308 if nil != err { 309 tErr := fmt.Sprintf("AccountHead(\"TestAccount\") failed: %v", err) 310 t.Fatalf(tErr) 311 } 312 accountCatHeader, ok = accountHeaders["Cat"] 313 if !ok { 314 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\"") 315 } 316 if (1 != len(accountCatHeader)) || ("Dog" != accountCatHeader[0]) { 317 t.Fatalf("AccountHead(\"TestAccount\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 318 } 319 _, ok = accountHeaders["Mouse"] 320 if ok { 321 t.Fatalf("AccountHead(\"TestAccount\") shouldn't have returned Header \"Mouse\"") 322 } 323 324 // Send a PUT for container "TestContainer" and header Cat: Dog 325 326 err = swiftclient.ContainerPut("TestAccount", "TestContainer", catDogHeaderMap) 327 if nil != err { 328 tErr := fmt.Sprintf("ContainerPut(\"TestAccount\", \"TestContainer\", catDogHeaderMap) failed: %v", err) 329 t.Fatalf(tErr) 330 } 331 332 // Send a GET for account "TestAccount" expecting header Cat: Dog and containerList []string{"TestContainer"} 333 334 accountHeaders, containerList, err = swiftclient.AccountGet("TestAccount") 335 if nil != err { 336 tErr := fmt.Sprintf("AccountGet(\"TestAccount\") failed: %v", err) 337 t.Fatalf(tErr) 338 } 339 accountCatHeader, ok = accountHeaders["Cat"] 340 if !ok { 341 t.Fatalf("AccountGet(\"TestAccount\") didn't return Header \"Cat\"") 342 } 343 if (1 != len(accountCatHeader)) || ("Dog" != accountCatHeader[0]) { 344 t.Fatalf("AccountGet(\"TestAccount\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 345 } 346 if (1 != len(containerList)) || ("TestContainer" != containerList[0]) { 347 t.Fatalf("AccountGet(\"TestAccount\") didn't return expected containerList") 348 } 349 350 // Send a HEAD for container "TestContainer" expecting header Cat: Dog 351 352 containerHeaders, err := swiftclient.ContainerHead("TestAccount", "TestContainer") 353 if nil != err { 354 tErr := fmt.Sprintf("ContainerHead(\"TestAccount\", \"TestContainer\") failed: %v", err) 355 t.Fatalf(tErr) 356 } 357 containerCatHeader, ok := containerHeaders["Cat"] 358 if !ok { 359 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 360 } 361 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 362 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 363 } 364 365 // Send a GET for container "TestContainer" expecting header Cat: Dog and objectList []string{} 366 367 containerHeaders, objectList, err := swiftclient.ContainerGet("TestAccount", "TestContainer") 368 if nil != err { 369 tErr := fmt.Sprintf("ContainerGet(\"TestAccount\", \"TestContainer\") failed: %v", err) 370 t.Fatalf(tErr) 371 } 372 containerCatHeader, ok = containerHeaders["Cat"] 373 if !ok { 374 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 375 } 376 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 377 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 378 } 379 if 0 != len(objectList) { 380 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return expected objectList") 381 } 382 383 // Send a POST for container "TestContainer" adding header Mouse: Bird 384 385 err = swiftclient.ContainerPost("TestAccount", "TestContainer", mouseBirdHeaderMap) 386 if nil != err { 387 tErr := fmt.Sprintf("ContainerPost(\"TestAccount\", \"TestContainer\", mouseBirdHeaderMap) failed: %v", err) 388 t.Fatalf(tErr) 389 } 390 391 // Send a HEAD for container "TestContainer" expecting header Cat: Dog & Mouse: Bird 392 393 containerHeaders, err = swiftclient.ContainerHead("TestAccount", "TestContainer") 394 if nil != err { 395 tErr := fmt.Sprintf("ContainerHead(\"TestAccount\", \"TestContainer\") failed: %v", err) 396 t.Fatalf(tErr) 397 } 398 containerCatHeader, ok = containerHeaders["Cat"] 399 if !ok { 400 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 401 } 402 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 403 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 404 } 405 containerMouseHeader, ok := containerHeaders["Mouse"] 406 if !ok { 407 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Mouse\"") 408 } 409 if (1 != len(containerMouseHeader)) || ("Bird" != containerMouseHeader[0]) { 410 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Mouse\" having value []string{\"Bird\"}") 411 } 412 413 // Send a POST for container "TestContainer" deleting header Mouse 414 415 err = swiftclient.ContainerPost("TestAccount", "TestContainer", mouseDeleteHeaderMap) 416 if nil != err { 417 tErr := fmt.Sprintf("ContainerPost(\"TestAccount\", \"TestContainer\", mouseDeleteHeaderMap) failed: %v", err) 418 t.Fatalf(tErr) 419 } 420 421 // Send a HEAD for container "TestContainer" expecting header Cat: Dog & no Mouse header 422 423 containerHeaders, err = swiftclient.ContainerHead("TestAccount", "TestContainer") 424 if nil != err { 425 tErr := fmt.Sprintf("ContainerHead(\"TestAccount\", \"TestContainer\") failed: %v", err) 426 t.Fatalf(tErr) 427 } 428 containerCatHeader, ok = containerHeaders["Cat"] 429 if !ok { 430 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 431 } 432 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 433 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 434 } 435 _, ok = containerHeaders["Mouse"] 436 if ok { 437 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") shouldn't have returned Header \"Mouse\"") 438 } 439 440 // Send a PUT for container "TestContainer" adding header Mouse: Bird 441 442 err = swiftclient.ContainerPut("TestAccount", "TestContainer", mouseBirdHeaderMap) 443 if nil != err { 444 tErr := fmt.Sprintf("ContainerPut(\"TestAccount\", \"TestContainer\", mouseBirdHeaderMap) failed: %v", err) 445 t.Fatalf(tErr) 446 } 447 448 // Send a HEAD for container "TestContainer" expecting header Cat: Dog & Mouse: Bird 449 450 containerHeaders, err = swiftclient.ContainerHead("TestAccount", "TestContainer") 451 if nil != err { 452 tErr := fmt.Sprintf("ContainerHead(\"TestAccount\", \"TestContainer\") failed: %v", err) 453 t.Fatalf(tErr) 454 } 455 containerCatHeader, ok = containerHeaders["Cat"] 456 if !ok { 457 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 458 } 459 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 460 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 461 } 462 containerMouseHeader, ok = containerHeaders["Mouse"] 463 if !ok { 464 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Mouse\"") 465 } 466 if (1 != len(containerMouseHeader)) || ("Bird" != containerMouseHeader[0]) { 467 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Mouse\" having value []string{\"Bird\"}") 468 } 469 470 // Send a PUT for container "TestContainer" deleting header Mouse 471 472 err = swiftclient.ContainerPut("TestAccount", "TestContainer", mouseDeleteHeaderMap) 473 if nil != err { 474 tErr := fmt.Sprintf("ContainerPut(\"TestAccount\", \"TestContainer\", mouseDeleteHeaderMap) failed: %v", err) 475 t.Fatalf(tErr) 476 } 477 478 // Send a HEAD for container "TestContainer" expecting header Cat: Dog & no Mouse header 479 480 containerHeaders, err = swiftclient.ContainerHead("TestAccount", "TestContainer") 481 if nil != err { 482 tErr := fmt.Sprintf("ContainerHead(\"TestAccount\", \"TestContainer\") failed: %v", err) 483 t.Fatalf(tErr) 484 } 485 containerCatHeader, ok = containerHeaders["Cat"] 486 if !ok { 487 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 488 } 489 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 490 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 491 } 492 _, ok = containerHeaders["Mouse"] 493 if ok { 494 t.Fatalf("ContainerHead(\"TestAccount\", \"TestContainer\") shouldn't have returned Header \"Mouse\"") 495 } 496 497 // Start a chunked PUT for object "FooBar" 498 499 chunkedPutContext, err := swiftclient.ObjectFetchChunkedPutContext("TestAccount", "TestContainer", "FooBar", "") 500 if nil != err { 501 tErr := fmt.Sprintf("ObjectFetchChunkedPutContext(\"TestAccount\", \"TestContainer\") failed: %v", err) 502 t.Fatalf(tErr) 503 } 504 505 // Send a chunk for object "FooBar" of []byte{0xAA, 0xBB} 506 507 err = chunkedPutContext.SendChunk([]byte{0xAA, 0xBB}) 508 if nil != err { 509 tErr := fmt.Sprintf("chunkedPutContext.SendChunk([]byte{0xAA, 0xBB}) failed: %v", err) 510 t.Fatalf(tErr) 511 } 512 513 // Send a chunk for object "FooBar" of []byte{0xCC, 0xDD, 0xEE} 514 515 err = chunkedPutContext.SendChunk([]byte{0xCC, 0xDD, 0xEE}) 516 if nil != err { 517 tErr := fmt.Sprintf("chunkedPutContext.SendChunk([]byte{0xCC, 0xDD, 0xEE}) failed: %v", err) 518 t.Fatalf(tErr) 519 } 520 521 // Fetch BytesPut for object "FooBar" expecting 5 522 523 bytesPut, err := chunkedPutContext.BytesPut() 524 if nil != err { 525 tErr := fmt.Sprintf("chunkedPutContext.BytesPut() failed: %v", err) 526 t.Fatalf(tErr) 527 } 528 if 5 != bytesPut { 529 t.Fatalf("chunkedPutContext.BytesPut() didn't return expected bytesPut") 530 } 531 532 // Read back chunked PUT data at offset 1 for length 3 expecting []byte{0xBB, 0xCC, 0xDD} 533 534 readBuf, err := chunkedPutContext.Read(uint64(1), uint64(3)) 535 if nil != err { 536 tErr := fmt.Sprintf("chunkedPutContext.Read(uint64(1), uint64(3)) failed: %v", err) 537 t.Fatalf(tErr) 538 } 539 if 0 != bytes.Compare([]byte{0xBB, 0xCC, 0xDD}, readBuf) { 540 t.Fatalf("chunkedPutContext.Read(uint64(1), uint64(3)) didn't return expected []byte") 541 } 542 543 // Finish the chunked PUT for object "FooBar" 544 545 err = chunkedPutContext.Close() 546 if nil != err { 547 tErr := fmt.Sprintf("chunkedPutContext.Close() failed: %v", err) 548 t.Fatalf(tErr) 549 } 550 551 // Send a GET for container "TestContainer" expecting header Cat: Dog and objectList []string{"FooBar"} 552 553 containerHeaders, objectList, err = swiftclient.ContainerGet("TestAccount", "TestContainer") 554 if nil != err { 555 tErr := fmt.Sprintf("ContainerGet(\"TestAccount\", \"TestContainer\") failed: %v", err) 556 t.Fatalf(tErr) 557 } 558 containerCatHeader, ok = containerHeaders["Cat"] 559 if !ok { 560 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 561 } 562 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 563 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 564 } 565 if (1 != len(objectList)) || ("FooBar" != objectList[0]) { 566 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return expected objectList") 567 } 568 569 // Send a HEAD for object "FooBar" expecting Content-Length: 5 570 571 objectHeaders, err := swiftclient.ObjectHead("TestAccount", "TestContainer", "FooBar") 572 if nil != err { 573 tErr := fmt.Sprintf("ObjectHead(\"TestAccount\", \"TestContainer\", \"FooBar\") failed: %v", err) 574 t.Fatalf(tErr) 575 } 576 contentLengthHeader, ok := objectHeaders["Content-Length"] 577 if !ok { 578 t.Fatalf("ObjectHead(\"TestAccount\", \"TestContainer\", \"FooBar\") didn't return Header \"Content-Length\"") 579 } 580 if (1 != len(contentLengthHeader)) || ("5" != contentLengthHeader[0]) { 581 t.Fatalf("ObjectHead(\"TestAccount\", \"TestContainer\", \"FooBar\") didn't return Header \"Content-Length\" having value []string{\"5\"}") 582 } 583 584 // Fetch Content-Length for object "FooBar" expecting 5 585 586 objectLength, err := swiftclient.ObjectContentLength("TestAccount", "TestContainer", "FooBar") 587 if nil != err { 588 tErr := fmt.Sprintf("ObjectContentLength(\"TestAccount\", \"TestContainer\", \"FooBar\") failed: %v", err) 589 t.Fatalf(tErr) 590 } 591 if uint64(5) != objectLength { 592 tErr := fmt.Sprintf("ObjectContentLength(\"TestAccount\", \"TestContainer\", \"FooBar\") didn't return expected Content-Length") 593 t.Fatalf(tErr) 594 } 595 596 // Send a range GET of bytes at offset 1 for length 3 for object "FooBar" expecting []byte{0xBB, 0xCC, 0xDD} 597 598 getBuf, err := swiftclient.ObjectGet("TestAccount", "TestContainer", "FooBar", uint64(1), uint64(3)) 599 if nil != err { 600 tErr := fmt.Sprintf("ObjectGet(\"TestAccount\", \"TestContainer\", \"FooBar\", uint64(1), uint64(3)) failed: %v", err) 601 t.Fatalf(tErr) 602 } 603 if 0 != bytes.Compare([]byte{0xBB, 0xCC, 0xDD}, getBuf) { 604 tErr := fmt.Sprintf("ObjectGet(\"TestAccount\", \"TestContainer\", \"FooBar\", uint64(1), uint64(3)) didn't return expected []byte") 605 t.Fatalf(tErr) 606 } 607 608 // Send a full GET for object "FooBar" expecting []byte{0xAA, 0xBB, 0xCC, 0xDD, OxEE} 609 610 loadBuf, err := swiftclient.ObjectLoad("TestAccount", "TestContainer", "FooBar") 611 if nil != err { 612 tErr := fmt.Sprintf("ObjectLoad(\"TestAccount\", \"TestContainer\", \"FooBar\") failed: %v", err) 613 t.Fatalf(tErr) 614 } 615 if 0 != bytes.Compare([]byte{0xAA, 0xBB, 0xCC, 0xDD, 0xEE}, loadBuf) { 616 tErr := fmt.Sprintf("ObjectLoad(\"TestAccount\", \"TestContainer\", \"FooBar\") didn't return expected []byte") 617 t.Fatalf(tErr) 618 } 619 620 // Send a tail GET of the last 2 bytes for object "FooBar" expecting []byte{0xDD, 0xEE} 621 622 tailBuf, err := swiftclient.ObjectTail("TestAccount", "TestContainer", "FooBar", uint64(2)) 623 if nil != err { 624 tErr := fmt.Sprintf("ObjectTail(\"TestAccount\", \"TestContainer\", \"FooBar\", uint64(2)) failed: %v", err) 625 t.Fatalf(tErr) 626 } 627 if 0 != bytes.Compare([]byte{0xDD, 0xEE}, tailBuf) { 628 tErr := fmt.Sprintf("ObjectTail(\"TestAccount\", \"TestContainer\", \"FooBar\", uint64(2)) didn't return expected []byte") 629 t.Fatalf(tErr) 630 } 631 632 // Copy object "FooBar" to object "FooBarCopy" 633 634 tOCCS := &testObjectCopyCallbackStruct{ 635 srcAccountName: "TestAccount", 636 srcContainerName: "TestContainer", 637 srcObjectName: "FooBar", 638 dstAccountName: "TestAccount", 639 dstContainerName: "TestContainer", 640 dstObjectName: "FooBarCopy", 641 chunkSize: 1, // Causes a callback for each of the five bytes of FooBar 642 } 643 644 err = swiftclient.ObjectCopy(tOCCS.srcAccountName, tOCCS.srcContainerName, tOCCS.srcObjectName, tOCCS.dstAccountName, tOCCS.dstContainerName, tOCCS.dstObjectName, tOCCS) 645 if nil != err { 646 tErr := fmt.Sprintf("ObjectCopy(\"TestAccount/TestContainer/FooBar\" to \"TestAccount/TestContainer/FooBarCopy\") failed: %v", err) 647 t.Fatalf(tErr) 648 } 649 650 // Send a full GET for object "FooBarCopy" expecting []byte{0xAA, 0xBB, 0xCC, 0xDD, OxEE} 651 652 loadBuf, err = swiftclient.ObjectLoad("TestAccount", "TestContainer", "FooBarCopy") 653 if nil != err { 654 tErr := fmt.Sprintf("ObjectLoad(\"TestAccount\", \"TestContainer\", \"FooBarCopy\") failed: %v", err) 655 t.Fatalf(tErr) 656 } 657 if 0 != bytes.Compare([]byte{0xAA, 0xBB, 0xCC, 0xDD, 0xEE}, loadBuf) { 658 tErr := fmt.Sprintf("ObjectLoad(\"TestAccount\", \"TestContainer\", \"FooBarCopy\") didn't return expected []byte") 659 t.Fatalf(tErr) 660 } 661 662 // Send a GET for container "TestContainer" expecting header Cat: Dog and objectList []string{"FooBar", "FooBarCopy"} 663 664 containerHeaders, objectList, err = swiftclient.ContainerGet("TestAccount", "TestContainer") 665 if nil != err { 666 tErr := fmt.Sprintf("ContainerGet(\"TestAccount\", \"TestContainer\") failed: %v", err) 667 t.Fatalf(tErr) 668 } 669 containerCatHeader, ok = containerHeaders["Cat"] 670 if !ok { 671 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 672 } 673 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 674 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 675 } 676 if (2 != len(objectList)) || ("FooBar" != objectList[0]) || ("FooBarCopy" != objectList[1]) { 677 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return expected objectList") 678 } 679 680 // Send a DELETE for object "FooBar" 681 682 err = swiftclient.ObjectDelete("TestAccount", "TestContainer", "FooBar", 0) 683 if nil != err { 684 tErr := fmt.Sprintf("ObjectDelete(\"TestAccount\", \"TestContainer\". \"FooBar\", 0) failed: %v", err) 685 t.Fatalf(tErr) 686 } 687 688 // Send a GET for container "TestContainer" expecting header Cat: Dog and objectList []string{"FooBarCopy"} 689 690 containerHeaders, objectList, err = swiftclient.ContainerGet("TestAccount", "TestContainer") 691 if nil != err { 692 tErr := fmt.Sprintf("ContainerGet(\"TestAccount\", \"TestContainer\") failed: %v", err) 693 t.Fatalf(tErr) 694 } 695 containerCatHeader, ok = containerHeaders["Cat"] 696 if !ok { 697 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 698 } 699 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 700 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 701 } 702 if (1 != len(objectList)) || ("FooBarCopy" != objectList[0]) { 703 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return expected objectList") 704 } 705 706 // Send a DELETE for object "FooBarCopy" 707 708 err = swiftclient.ObjectDelete("TestAccount", "TestContainer", "FooBarCopy", 0) 709 if nil != err { 710 tErr := fmt.Sprintf("ObjectDelete(\"TestAccount\", \"TestContainer\". \"FooBarCopy\", 0) failed: %v", err) 711 t.Fatalf(tErr) 712 } 713 714 // Send a GET for container "TestContainer" expecting header Cat: Dog and objectList []string{} 715 716 containerHeaders, objectList, err = swiftclient.ContainerGet("TestAccount", "TestContainer") 717 if nil != err { 718 tErr := fmt.Sprintf("ContainerGet(\"TestAccount\", \"TestContainer\") failed: %v", err) 719 t.Fatalf(tErr) 720 } 721 containerCatHeader, ok = containerHeaders["Cat"] 722 if !ok { 723 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\"") 724 } 725 if (1 != len(containerCatHeader)) || ("Dog" != containerCatHeader[0]) { 726 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 727 } 728 if 0 != len(objectList) { 729 t.Fatalf("ContainerGet(\"TestAccount\", \"TestContainer\") didn't return expected objectList") 730 } 731 732 // Send a DELETE for container "TestContainer" 733 734 err = swiftclient.ContainerDelete("TestAccount", "TestContainer") 735 if nil != err { 736 tErr := fmt.Sprintf("ContainerDelete(\"TestAccount\", \"TestContainer\") failed: %v", err) 737 t.Fatalf(tErr) 738 } 739 740 // create and delete container "TestContainer" again so we're sure the retry code is hit 741 742 err = swiftclient.ContainerPut("TestAccount", "TestContainer", catDogHeaderMap) 743 if nil != err { 744 tErr := fmt.Sprintf("ContainerPut(\"TestAccount\", \"TestContainer\", catDogHeaderMap) failed: %v", err) 745 t.Fatalf(tErr) 746 } 747 err = swiftclient.ContainerDelete("TestAccount", "TestContainer") 748 if nil != err { 749 tErr := fmt.Sprintf("ContainerDelete(\"TestAccount\", \"TestContainer\") failed: %v", err) 750 t.Fatalf(tErr) 751 } 752 753 // Send a GET for account "TestAccount" expecting header Cat: Dog and containerList []string{} 754 755 accountHeaders, containerList, err = swiftclient.AccountGet("TestAccount") 756 if nil != err { 757 tErr := fmt.Sprintf("AccountGet(\"TestAccount\") failed: %v", err) 758 t.Fatalf(tErr) 759 } 760 accountCatHeader, ok = accountHeaders["Cat"] 761 if !ok { 762 t.Fatalf("AccountGet(\"TestAccount\") didn't return Header \"Cat\"") 763 } 764 if (1 != len(accountCatHeader)) || ("Dog" != accountCatHeader[0]) { 765 t.Fatalf("AccountGet(\"TestAccount\") didn't return Header \"Cat\" having value []string{\"Dog\"}") 766 } 767 if 0 != len(containerList) { 768 t.Fatalf("AccountGet(\"TestAccount\") didn't return expected containerList") 769 } 770 771 // Send a DELETE for account "TestAccount" 772 773 err = swiftclient.AccountDelete("TestAccount") 774 if nil != err { 775 tErr := fmt.Sprintf("AccountDelete(\"TestAccount\") failed: %v", err) 776 t.Fatalf(tErr) 777 } 778 779 // Create and delete "TestAccount" again so we're sure the retry code is hit 780 781 err = swiftclient.AccountPut("TestAccount", catDogHeaderMap) 782 if nil != err { 783 tErr := fmt.Sprintf("AccountPut(\"TestAccount\", catDogHeaderMap) failed: %v", err) 784 t.Fatalf(tErr) 785 } 786 err = swiftclient.AccountDelete("TestAccount") 787 if nil != err { 788 tErr := fmt.Sprintf("AccountDelete(\"TestAccount\") failed: %v", err) 789 t.Fatalf(tErr) 790 } 791 } 792 793 // Extended testing of chunked put interface to exercise internal retries 794 // 795 func testChunkedPut(t *testing.T) { 796 var ( 797 accountName = "TestAccount" 798 containerName = "TestContainer" 799 objNameFmt = "chunkObj%d" 800 objName string 801 ) 802 803 // (lack of) headers for putting 804 catDogHeaderMap := make(map[string][]string) 805 806 // (re)create the test account and continer 807 808 err := swiftclient.AccountPut(accountName, catDogHeaderMap) 809 if nil != err { 810 tErr := fmt.Sprintf("testChunkedPut.AccountPut('%s', catDogHeaderMap) failed: %v", accountName, err) 811 t.Fatalf(tErr) 812 } 813 814 err = swiftclient.ContainerPut(accountName, containerName, catDogHeaderMap) 815 if nil != err { 816 tErr := fmt.Sprintf("testChunkedPut.ContainerPut('%s', '%s', catDogHeaderMap) failed: %v", 817 accountName, containerName, err) 818 t.Fatalf(tErr) 819 } 820 821 for i := 0; i < 5; i++ { 822 objName = fmt.Sprintf(objNameFmt, i) 823 824 err = testObjectWriteVerify(t, accountName, containerName, objName, 4096, 4) 825 if nil != err { 826 tErr := fmt.Sprintf("testChunkedPut.testObjectWriteVerify('%s/%s/%s', %d, %d ) failed: %v", 827 accountName, containerName, objName, 4096, 4, err) 828 t.Fatalf(tErr) 829 } 830 } 831 832 // cleanup the mess we made (objects, container, and account) 833 for i := 0; i < 5; i++ { 834 objName = fmt.Sprintf(objNameFmt, i) 835 836 err = swiftclient.ObjectDelete(accountName, containerName, objName, 0) 837 if nil != err { 838 tErr := fmt.Sprintf("ObjectDelete('%s', '%s', '%s') failed: %v", 839 accountName, containerName, objName, err) 840 t.Fatalf(tErr) 841 } 842 } 843 844 err = swiftclient.ContainerDelete(accountName, containerName) 845 if nil != err { 846 tErr := fmt.Sprintf("ContainerDelete('%s', '%s') failed: %v", accountName, containerName, err) 847 t.Fatalf(tErr) 848 } 849 850 err = swiftclient.AccountDelete(accountName) 851 if nil != err { 852 tErr := fmt.Sprintf("AccountDelete('%s') failed: %v", accountName, err) 853 t.Fatalf(tErr) 854 } 855 } 856 857 // write objSize worth of random bytes to the object using nWrite calls to 858 // SendChunk() and then read it back to verify. 859 // 860 func testObjectWriteVerify(t *testing.T, accountName string, containerName string, objName string, 861 objSize int, nwrite int) (err error) { 862 863 writeBuf := make([]byte, objSize) 864 readBuf := make([]byte, 0) 865 866 for i := 0; i < objSize; i++ { 867 writeBuf[i] = byte(rand.Uint32()) 868 } 869 if writeBuf[0] == 0 && writeBuf[1] == 0 && writeBuf[2] == 0 && writeBuf[3] == 0 { 870 tErr := "unix.GetRandom() is not very random" 871 t.Fatalf(tErr) 872 } 873 if writeBuf[objSize-1] == 0 && writeBuf[objSize-2] == 0 && writeBuf[objSize-3] == 0 && 874 writeBuf[objSize-4] == 0 { 875 tErr := "unix.GetRandom() is not very radnom at end of buffer" 876 t.Fatalf(tErr) 877 } 878 879 // Start a chunked PUT for the object 880 chunkedPutContext, err := swiftclient.ObjectFetchChunkedPutContext(accountName, containerName, objName, "") 881 if nil != err { 882 tErr := fmt.Sprintf("ObjectFetchChunkedPutContext('%s', '%s', '%s') failed: %v", 883 accountName, containerName, objName, err) 884 return errors.New(tErr) 885 } 886 887 wsz := len(writeBuf) / nwrite 888 for off := 0; off < len(writeBuf); off += wsz { 889 if off+wsz < objSize { 890 err = chunkedPutContext.SendChunk(writeBuf[off : off+wsz]) 891 } else { 892 err = chunkedPutContext.SendChunk(writeBuf[off:]) 893 } 894 if nil != err { 895 tErr := fmt.Sprintf("chunkedPutContext.SendChunk(writeBuf[%d:%d]) failed: %v", 896 off, off+wsz, err) 897 return errors.New(tErr) 898 } 899 } 900 err = chunkedPutContext.Close() 901 if nil != err { 902 tErr := fmt.Sprintf("chunkedPutContext.Close('%s/%s/%s') failed: %v", 903 accountName, containerName, objName, err) 904 return errors.New(tErr) 905 } 906 907 // read and compare 908 readBuf, err = swiftclient.ObjectLoad(accountName, containerName, objName) 909 if nil != err { 910 tErr := fmt.Sprintf("ObjectLoad('%s/%s/%s') failed: %v", accountName, containerName, objName, err) 911 return errors.New(tErr) 912 } 913 if !bytes.Equal(readBuf, writeBuf) { 914 tErr := fmt.Sprintf("Object('%s/%s/%s') read back something different then written", 915 accountName, containerName, objName) 916 return errors.New(tErr) 917 } 918 919 return nil 920 } 921 922 // Make sure we can shutdown and re-enable the statsLogger 923 // 924 func testReload(t *testing.T, confMap conf.ConfMap) { 925 var err error 926 927 // Reload statslogger with logging disabled 928 err = confMap.UpdateFromString("StatsLogger.Period=0s") 929 if nil != err { 930 tErr := fmt.Sprintf("UpdateFromString('StatsLogger.Period=0s') failed: %v", err) 931 t.Fatalf(tErr) 932 } 933 934 err = transitions.Signaled(confMap) 935 if nil != err { 936 t.Fatalf("transitions.Signaled(confMap) failed: %v", err) 937 } 938 939 // Enable logging again 940 err = confMap.UpdateFromString("StatsLogger.Period=1s") 941 if nil != err { 942 tErr := fmt.Sprintf("UpdateFromString('StatsLogger.Period=1s') failed: %v", err) 943 t.Fatalf(tErr) 944 } 945 946 err = transitions.Signaled(confMap) 947 if nil != err { 948 t.Fatalf("transitions.Signaled(confMap) failed: %v", err) 949 } 950 }