1package request_test 2 3import ( 4 "reflect" 5 "testing" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/aws/request" 9 "github.com/aws/aws-sdk-go/awstesting" 10 "github.com/aws/aws-sdk-go/awstesting/unit" 11 "github.com/aws/aws-sdk-go/service/dynamodb" 12 "github.com/aws/aws-sdk-go/service/route53" 13 "github.com/aws/aws-sdk-go/service/s3" 14) 15 16// Use DynamoDB methods for simplicity 17func TestPaginationQueryPage(t *testing.T) { 18 db := dynamodb.New(unit.Session) 19 tokens, pages, numPages, gotToEnd := []map[string]*dynamodb.AttributeValue{}, []map[string]*dynamodb.AttributeValue{}, 0, false 20 21 reqNum := 0 22 resps := []*dynamodb.QueryOutput{ 23 { 24 LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key1")}}, 25 Count: aws.Int64(1), 26 Items: []map[string]*dynamodb.AttributeValue{ 27 { 28 "key": {S: aws.String("key1")}, 29 }, 30 }, 31 }, 32 { 33 LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key2")}}, 34 Count: aws.Int64(1), 35 Items: []map[string]*dynamodb.AttributeValue{ 36 { 37 "key": {S: aws.String("key2")}, 38 }, 39 }, 40 }, 41 { 42 LastEvaluatedKey: map[string]*dynamodb.AttributeValue{}, 43 Count: aws.Int64(1), 44 Items: []map[string]*dynamodb.AttributeValue{ 45 { 46 "key": {S: aws.String("key3")}, 47 }, 48 }, 49 }, 50 } 51 52 db.Handlers.Send.Clear() // mock sending 53 db.Handlers.Unmarshal.Clear() 54 db.Handlers.UnmarshalMeta.Clear() 55 db.Handlers.ValidateResponse.Clear() 56 db.Handlers.Build.PushBack(func(r *request.Request) { 57 in := r.Params.(*dynamodb.QueryInput) 58 if in == nil { 59 tokens = append(tokens, nil) 60 } else if len(in.ExclusiveStartKey) != 0 { 61 tokens = append(tokens, in.ExclusiveStartKey) 62 } 63 }) 64 db.Handlers.Unmarshal.PushBack(func(r *request.Request) { 65 r.Data = resps[reqNum] 66 reqNum++ 67 }) 68 69 params := &dynamodb.QueryInput{ 70 Limit: aws.Int64(2), 71 TableName: aws.String("tablename"), 72 } 73 err := db.QueryPages(params, func(p *dynamodb.QueryOutput, last bool) bool { 74 numPages++ 75 pages = append(pages, p.Items...) 76 if last { 77 if gotToEnd { 78 t.Errorf("last=true happened twice") 79 } 80 gotToEnd = true 81 } 82 return true 83 }) 84 if err != nil { 85 t.Errorf("expect nil, %v", err) 86 } 87 88 if e, a := 89 []map[string]*dynamodb.AttributeValue{ 90 {"key": {S: aws.String("key1")}}, 91 {"key": {S: aws.String("key2")}}, 92 }, tokens; !reflect.DeepEqual(e, a) { 93 t.Errorf("expect %v, got %v", e, a) 94 } 95 if e, a := 96 []map[string]*dynamodb.AttributeValue{ 97 {"key": {S: aws.String("key1")}}, 98 {"key": {S: aws.String("key2")}}, 99 {"key": {S: aws.String("key3")}}, 100 }, pages; !reflect.DeepEqual(e, a) { 101 t.Errorf("expect %v, got %v", e, a) 102 } 103 if e, a := 3, numPages; e != a { 104 t.Errorf("expect %v, got %v", e, a) 105 } 106 if !gotToEnd { 107 t.Errorf("expect true") 108 } 109 if params.ExclusiveStartKey != nil { 110 t.Errorf("expect nil, %v", err) 111 } 112} 113 114// Use DynamoDB methods for simplicity 115func TestPagination(t *testing.T) { 116 db := dynamodb.New(unit.Session) 117 tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false 118 119 reqNum := 0 120 resps := []*dynamodb.ListTablesOutput{ 121 {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, 122 {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, 123 {TableNames: []*string{aws.String("Table5")}}, 124 } 125 126 db.Handlers.Send.Clear() // mock sending 127 db.Handlers.Unmarshal.Clear() 128 db.Handlers.UnmarshalMeta.Clear() 129 db.Handlers.ValidateResponse.Clear() 130 db.Handlers.Build.PushBack(func(r *request.Request) { 131 in := r.Params.(*dynamodb.ListTablesInput) 132 if in == nil { 133 tokens = append(tokens, "") 134 } else if in.ExclusiveStartTableName != nil { 135 tokens = append(tokens, *in.ExclusiveStartTableName) 136 } 137 }) 138 db.Handlers.Unmarshal.PushBack(func(r *request.Request) { 139 r.Data = resps[reqNum] 140 reqNum++ 141 }) 142 143 params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} 144 err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool { 145 numPages++ 146 for _, t := range p.TableNames { 147 pages = append(pages, *t) 148 } 149 if last { 150 if gotToEnd { 151 t.Errorf("last=true happened twice") 152 } 153 gotToEnd = true 154 } 155 return true 156 }) 157 158 if e, a := []string{"Table2", "Table4"}, tokens; !reflect.DeepEqual(e, a) { 159 t.Errorf("expect %v, got %v", e, a) 160 } 161 if e, a := []string{"Table1", "Table2", "Table3", "Table4", "Table5"}, pages; !reflect.DeepEqual(e, a) { 162 t.Errorf("expect %v, got %v", e, a) 163 } 164 if e, a := 3, numPages; e != a { 165 t.Errorf("expect %v, got %v", e, a) 166 } 167 if !gotToEnd { 168 t.Errorf("expect true") 169 } 170 if err != nil { 171 t.Errorf("expect nil, %v", err) 172 } 173 if params.ExclusiveStartTableName != nil { 174 t.Errorf("expect nil, %v", err) 175 } 176} 177 178// Use DynamoDB methods for simplicity 179func TestPaginationEachPage(t *testing.T) { 180 db := dynamodb.New(unit.Session) 181 tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false 182 183 reqNum := 0 184 resps := []*dynamodb.ListTablesOutput{ 185 {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, 186 {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, 187 {TableNames: []*string{aws.String("Table5")}}, 188 } 189 190 db.Handlers.Send.Clear() // mock sending 191 db.Handlers.Unmarshal.Clear() 192 db.Handlers.UnmarshalMeta.Clear() 193 db.Handlers.ValidateResponse.Clear() 194 db.Handlers.Build.PushBack(func(r *request.Request) { 195 in := r.Params.(*dynamodb.ListTablesInput) 196 if in == nil { 197 tokens = append(tokens, "") 198 } else if in.ExclusiveStartTableName != nil { 199 tokens = append(tokens, *in.ExclusiveStartTableName) 200 } 201 }) 202 db.Handlers.Unmarshal.PushBack(func(r *request.Request) { 203 r.Data = resps[reqNum] 204 reqNum++ 205 }) 206 207 params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} 208 req, _ := db.ListTablesRequest(params) 209 err := req.EachPage(func(p interface{}, last bool) bool { 210 numPages++ 211 for _, t := range p.(*dynamodb.ListTablesOutput).TableNames { 212 pages = append(pages, *t) 213 } 214 if last { 215 if gotToEnd { 216 t.Errorf("last=true happened twice") 217 } 218 gotToEnd = true 219 } 220 221 return true 222 }) 223 224 if e, a := []string{"Table2", "Table4"}, tokens; !reflect.DeepEqual(e, a) { 225 t.Errorf("expect %v, got %v", e, a) 226 } 227 if e, a := []string{"Table1", "Table2", "Table3", "Table4", "Table5"}, pages; !reflect.DeepEqual(e, a) { 228 t.Errorf("expect %v, got %v", e, a) 229 } 230 if e, a := 3, numPages; e != a { 231 t.Errorf("expect %v, got %v", e, a) 232 } 233 if !gotToEnd { 234 t.Errorf("expect true") 235 } 236 if err != nil { 237 t.Errorf("expect nil, %v", err) 238 } 239} 240 241// Use DynamoDB methods for simplicity 242func TestPaginationEarlyExit(t *testing.T) { 243 db := dynamodb.New(unit.Session) 244 numPages, gotToEnd := 0, false 245 246 reqNum := 0 247 resps := []*dynamodb.ListTablesOutput{ 248 {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, 249 {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, 250 {TableNames: []*string{aws.String("Table5")}}, 251 } 252 253 db.Handlers.Send.Clear() // mock sending 254 db.Handlers.Unmarshal.Clear() 255 db.Handlers.UnmarshalMeta.Clear() 256 db.Handlers.ValidateResponse.Clear() 257 db.Handlers.Unmarshal.PushBack(func(r *request.Request) { 258 r.Data = resps[reqNum] 259 reqNum++ 260 }) 261 262 params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} 263 err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool { 264 numPages++ 265 if numPages == 2 { 266 return false 267 } 268 if last { 269 if gotToEnd { 270 t.Errorf("last=true happened twice") 271 } 272 gotToEnd = true 273 } 274 return true 275 }) 276 277 if e, a := 2, numPages; e != a { 278 t.Errorf("expect %v, got %v", e, a) 279 } 280 if gotToEnd { 281 t.Errorf("expect false") 282 } 283 if err != nil { 284 t.Errorf("expect nil, %v", err) 285 } 286} 287 288func TestSkipPagination(t *testing.T) { 289 client := s3.New(unit.Session) 290 client.Handlers.Send.Clear() // mock sending 291 client.Handlers.Unmarshal.Clear() 292 client.Handlers.UnmarshalMeta.Clear() 293 client.Handlers.ValidateResponse.Clear() 294 client.Handlers.Unmarshal.PushBack(func(r *request.Request) { 295 r.Data = &s3.HeadBucketOutput{} 296 }) 297 298 req, _ := client.HeadBucketRequest(&s3.HeadBucketInput{Bucket: aws.String("bucket")}) 299 300 numPages, gotToEnd := 0, false 301 req.EachPage(func(p interface{}, last bool) bool { 302 numPages++ 303 if last { 304 gotToEnd = true 305 } 306 return true 307 }) 308 if e, a := 1, numPages; e != a { 309 t.Errorf("expect %v, got %v", e, a) 310 } 311 if !gotToEnd { 312 t.Errorf("expect true") 313 } 314} 315 316// Use S3 for simplicity 317func TestPaginationTruncation(t *testing.T) { 318 client := s3.New(unit.Session) 319 320 reqNum := 0 321 resps := []*s3.ListObjectsOutput{ 322 {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key1")}}}, 323 {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key2")}}}, 324 {IsTruncated: aws.Bool(false), Contents: []*s3.Object{{Key: aws.String("Key3")}}}, 325 {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key4")}}}, 326 } 327 328 client.Handlers.Send.Clear() // mock sending 329 client.Handlers.Unmarshal.Clear() 330 client.Handlers.UnmarshalMeta.Clear() 331 client.Handlers.ValidateResponse.Clear() 332 client.Handlers.Unmarshal.PushBack(func(r *request.Request) { 333 r.Data = resps[reqNum] 334 reqNum++ 335 }) 336 337 params := &s3.ListObjectsInput{Bucket: aws.String("bucket")} 338 339 results := []string{} 340 err := client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool { 341 results = append(results, *p.Contents[0].Key) 342 return true 343 }) 344 345 if e, a := []string{"Key1", "Key2", "Key3"}, results; !reflect.DeepEqual(e, a) { 346 t.Errorf("expect %v, got %v", e, a) 347 } 348 if err != nil { 349 t.Errorf("expect nil, %v", err) 350 } 351 352 // Try again without truncation token at all 353 reqNum = 0 354 resps[1].IsTruncated = nil 355 resps[2].IsTruncated = aws.Bool(true) 356 results = []string{} 357 err = client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool { 358 results = append(results, *p.Contents[0].Key) 359 return true 360 }) 361 362 if e, a := []string{"Key1", "Key2"}, results; !reflect.DeepEqual(e, a) { 363 t.Errorf("expect %v, got %v", e, a) 364 } 365 if err != nil { 366 t.Errorf("expect nil, %v", err) 367 } 368} 369 370func TestPaginationNilToken(t *testing.T) { 371 client := route53.New(unit.Session) 372 373 reqNum := 0 374 resps := []*route53.ListResourceRecordSetsOutput{ 375 { 376 ResourceRecordSets: []*route53.ResourceRecordSet{ 377 {Name: aws.String("first.example.com.")}, 378 }, 379 IsTruncated: aws.Bool(true), 380 NextRecordName: aws.String("second.example.com."), 381 NextRecordType: aws.String("MX"), 382 NextRecordIdentifier: aws.String("second"), 383 MaxItems: aws.String("1"), 384 }, 385 { 386 ResourceRecordSets: []*route53.ResourceRecordSet{ 387 {Name: aws.String("second.example.com.")}, 388 }, 389 IsTruncated: aws.Bool(true), 390 NextRecordName: aws.String("third.example.com."), 391 NextRecordType: aws.String("MX"), 392 MaxItems: aws.String("1"), 393 }, 394 { 395 ResourceRecordSets: []*route53.ResourceRecordSet{ 396 {Name: aws.String("third.example.com.")}, 397 }, 398 IsTruncated: aws.Bool(false), 399 MaxItems: aws.String("1"), 400 }, 401 } 402 client.Handlers.Send.Clear() // mock sending 403 client.Handlers.Unmarshal.Clear() 404 client.Handlers.UnmarshalMeta.Clear() 405 client.Handlers.ValidateResponse.Clear() 406 407 idents := []string{} 408 client.Handlers.Build.PushBack(func(r *request.Request) { 409 p := r.Params.(*route53.ListResourceRecordSetsInput) 410 idents = append(idents, aws.StringValue(p.StartRecordIdentifier)) 411 412 }) 413 client.Handlers.Unmarshal.PushBack(func(r *request.Request) { 414 r.Data = resps[reqNum] 415 reqNum++ 416 }) 417 418 params := &route53.ListResourceRecordSetsInput{ 419 HostedZoneId: aws.String("id-zone"), 420 } 421 422 results := []string{} 423 err := client.ListResourceRecordSetsPages(params, func(p *route53.ListResourceRecordSetsOutput, last bool) bool { 424 results = append(results, *p.ResourceRecordSets[0].Name) 425 return true 426 }) 427 428 if err != nil { 429 t.Errorf("expect nil, %v", err) 430 } 431 if e, a := []string{"", "second", ""}, idents; !reflect.DeepEqual(e, a) { 432 t.Errorf("expect %v, got %v", e, a) 433 } 434 if e, a := []string{"first.example.com.", "second.example.com.", "third.example.com."}, results; !reflect.DeepEqual(e, a) { 435 t.Errorf("expect %v, got %v", e, a) 436 } 437} 438 439func TestPaginationNilInput(t *testing.T) { 440 // Code generation doesn't have a great way to verify the code is correct 441 // other than being run via unit tests in the SDK. This should be fixed 442 // So code generation can be validated independently. 443 444 client := s3.New(unit.Session) 445 client.Handlers.Validate.Clear() 446 client.Handlers.Send.Clear() // mock sending 447 client.Handlers.Unmarshal.Clear() 448 client.Handlers.UnmarshalMeta.Clear() 449 client.Handlers.ValidateResponse.Clear() 450 client.Handlers.Unmarshal.PushBack(func(r *request.Request) { 451 r.Data = &s3.ListObjectsOutput{} 452 }) 453 454 gotToEnd := false 455 numPages := 0 456 err := client.ListObjectsPages(nil, func(p *s3.ListObjectsOutput, last bool) bool { 457 numPages++ 458 if last { 459 gotToEnd = true 460 } 461 return true 462 }) 463 464 if err != nil { 465 t.Fatalf("expect no error, but got %v", err) 466 } 467 if e, a := 1, numPages; e != a { 468 t.Errorf("expect %d number pages but got %d", e, a) 469 } 470 if !gotToEnd { 471 t.Errorf("expect to of gotten to end, did not") 472 } 473} 474 475func TestPaginationWithContextNilInput(t *testing.T) { 476 // Code generation doesn't have a great way to verify the code is correct 477 // other than being run via unit tests in the SDK. This should be fixed 478 // So code generation can be validated independently. 479 480 client := s3.New(unit.Session) 481 client.Handlers.Validate.Clear() 482 client.Handlers.Send.Clear() // mock sending 483 client.Handlers.Unmarshal.Clear() 484 client.Handlers.UnmarshalMeta.Clear() 485 client.Handlers.ValidateResponse.Clear() 486 client.Handlers.Unmarshal.PushBack(func(r *request.Request) { 487 r.Data = &s3.ListObjectsOutput{} 488 }) 489 490 gotToEnd := false 491 numPages := 0 492 ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})} 493 err := client.ListObjectsPagesWithContext(ctx, nil, func(p *s3.ListObjectsOutput, last bool) bool { 494 numPages++ 495 if last { 496 gotToEnd = true 497 } 498 return true 499 }) 500 501 if err != nil { 502 t.Fatalf("expect no error, but got %v", err) 503 } 504 if e, a := 1, numPages; e != a { 505 t.Errorf("expect %d number pages but got %d", e, a) 506 } 507 if !gotToEnd { 508 t.Errorf("expect to of gotten to end, did not") 509 } 510} 511 512func TestPagination_Standalone(t *testing.T) { 513 type testPageInput struct { 514 NextToken *string 515 } 516 type testPageOutput struct { 517 Value *string 518 NextToken *string 519 } 520 type testCase struct { 521 Value, PrevToken, NextToken *string 522 } 523 524 type testCaseList struct { 525 StopOnSameToken bool 526 Cases []testCase 527 } 528 529 cases := []testCaseList{ 530 { 531 Cases: []testCase{ 532 {aws.String("FirstValue"), aws.String("InitalToken"), aws.String("FirstToken")}, 533 {aws.String("SecondValue"), aws.String("FirstToken"), aws.String("SecondToken")}, 534 {aws.String("ThirdValue"), aws.String("SecondToken"), nil}, 535 }, 536 StopOnSameToken: false, 537 }, 538 { 539 Cases: []testCase{ 540 {aws.String("FirstValue"), aws.String("InitalToken"), aws.String("FirstToken")}, 541 {aws.String("SecondValue"), aws.String("FirstToken"), aws.String("SecondToken")}, 542 {aws.String("ThirdValue"), aws.String("SecondToken"), aws.String("")}, 543 }, 544 StopOnSameToken: false, 545 }, 546 { 547 Cases: []testCase{ 548 {aws.String("FirstValue"), aws.String("InitalToken"), aws.String("FirstToken")}, 549 {aws.String("SecondValue"), aws.String("FirstToken"), aws.String("SecondToken")}, 550 {nil, aws.String("SecondToken"), aws.String("SecondToken")}, 551 }, 552 StopOnSameToken: true, 553 }, 554 { 555 Cases: []testCase{ 556 {aws.String("FirstValue"), aws.String("InitalToken"), aws.String("FirstToken")}, 557 {aws.String("SecondValue"), aws.String("FirstToken"), aws.String("SecondToken")}, 558 {aws.String("SecondValue"), aws.String("SecondToken"), aws.String("SecondToken")}, 559 }, 560 StopOnSameToken: true, 561 }, 562 } 563 564 for _, testcase := range cases { 565 c := testcase.Cases 566 input := testPageInput{ 567 NextToken: c[0].PrevToken, 568 } 569 570 svc := awstesting.NewClient() 571 i := 0 572 p := request.Pagination{ 573 EndPageOnSameToken: testcase.StopOnSameToken, 574 NewRequest: func() (*request.Request, error) { 575 r := svc.NewRequest( 576 &request.Operation{ 577 Name: "Operation", 578 Paginator: &request.Paginator{ 579 InputTokens: []string{"NextToken"}, 580 OutputTokens: []string{"NextToken"}, 581 }, 582 }, 583 &input, &testPageOutput{}, 584 ) 585 // Setup handlers for testing 586 r.Handlers.Clear() 587 r.Handlers.Build.PushBack(func(req *request.Request) { 588 if e, a := len(c), i+1; a > e { 589 t.Fatalf("expect no more than %d requests, got %d", e, a) 590 } 591 in := req.Params.(*testPageInput) 592 if e, a := aws.StringValue(c[i].PrevToken), aws.StringValue(in.NextToken); e != a { 593 t.Errorf("%d, expect NextToken input %q, got %q", i, e, a) 594 } 595 }) 596 r.Handlers.Unmarshal.PushBack(func(req *request.Request) { 597 out := &testPageOutput{ 598 Value: c[i].Value, 599 } 600 if c[i].NextToken != nil { 601 next := *c[i].NextToken 602 out.NextToken = aws.String(next) 603 } 604 req.Data = out 605 }) 606 return r, nil 607 }, 608 } 609 610 for p.Next() { 611 data := p.Page().(*testPageOutput) 612 613 if e, a := aws.StringValue(c[i].Value), aws.StringValue(data.Value); e != a { 614 t.Errorf("%d, expect Value to be %q, got %q", i, e, a) 615 } 616 if e, a := aws.StringValue(c[i].NextToken), aws.StringValue(data.NextToken); e != a { 617 t.Errorf("%d, expect NextToken to be %q, got %q", i, e, a) 618 } 619 620 i++ 621 } 622 if e, a := len(c), i; e != a { 623 t.Errorf("expected to process %d pages, did %d", e, a) 624 } 625 if err := p.Err(); err != nil { 626 t.Fatalf("%d, expected no error, got %v", i, err) 627 } 628 } 629} 630 631// Benchmarks 632var benchResps = []*dynamodb.ListTablesOutput{ 633 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 634 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 635 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 636 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 637 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 638 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 639 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 640 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 641 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 642 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 643 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 644 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 645 {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, 646 {TableNames: []*string{aws.String("TABLE")}}, 647} 648 649var benchDb = func() *dynamodb.DynamoDB { 650 db := dynamodb.New(unit.Session) 651 db.Handlers.Send.Clear() // mock sending 652 db.Handlers.Unmarshal.Clear() 653 db.Handlers.UnmarshalMeta.Clear() 654 db.Handlers.ValidateResponse.Clear() 655 return db 656} 657 658func BenchmarkCodegenIterator(b *testing.B) { 659 reqNum := 0 660 db := benchDb() 661 db.Handlers.Unmarshal.PushBack(func(r *request.Request) { 662 r.Data = benchResps[reqNum] 663 reqNum++ 664 }) 665 666 input := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} 667 iter := func(fn func(*dynamodb.ListTablesOutput, bool) bool) error { 668 page, _ := db.ListTablesRequest(input) 669 for ; page != nil; page = page.NextPage() { 670 page.Send() 671 out := page.Data.(*dynamodb.ListTablesOutput) 672 if result := fn(out, !page.HasNextPage()); page.Error != nil || !result { 673 return page.Error 674 } 675 } 676 return nil 677 } 678 679 for i := 0; i < b.N; i++ { 680 reqNum = 0 681 iter(func(p *dynamodb.ListTablesOutput, last bool) bool { 682 return true 683 }) 684 } 685} 686 687func BenchmarkEachPageIterator(b *testing.B) { 688 reqNum := 0 689 db := benchDb() 690 db.Handlers.Unmarshal.PushBack(func(r *request.Request) { 691 r.Data = benchResps[reqNum] 692 reqNum++ 693 }) 694 695 input := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} 696 for i := 0; i < b.N; i++ { 697 reqNum = 0 698 req, _ := db.ListTablesRequest(input) 699 req.EachPage(func(p interface{}, last bool) bool { 700 return true 701 }) 702 } 703} 704