github.com/prebid/prebid-server@v0.275.0/stored_responses/stored_responses_test.go (about) 1 package stored_responses 2 3 import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "testing" 8 9 "github.com/prebid/openrtb/v19/openrtb2" 10 "github.com/prebid/prebid-server/openrtb_ext" 11 "github.com/stretchr/testify/assert" 12 ) 13 14 func TestRemoveImpsWithStoredResponses(t *testing.T) { 15 bidRespId1 := json.RawMessage(`{"id": "resp_id1"}`) 16 testCases := []struct { 17 description string 18 reqIn *openrtb2.BidRequest 19 storedBidResponses ImpBidderStoredResp 20 expectedImps []openrtb2.Imp 21 }{ 22 { 23 description: "request with imps and stored bid response for this imp", 24 reqIn: &openrtb2.BidRequest{Imp: []openrtb2.Imp{ 25 {ID: "imp-id1"}, 26 }}, 27 storedBidResponses: ImpBidderStoredResp{ 28 "imp-id1": {"appnexus": bidRespId1}, 29 }, 30 expectedImps: nil, 31 }, 32 { 33 description: "request with imps and stored bid response for one of these imp", 34 reqIn: &openrtb2.BidRequest{Imp: []openrtb2.Imp{ 35 {ID: "imp-id1"}, 36 {ID: "imp-id2"}, 37 }}, 38 storedBidResponses: ImpBidderStoredResp{ 39 "imp-id1": {"appnexus": bidRespId1}, 40 }, 41 expectedImps: []openrtb2.Imp{ 42 { 43 ID: "imp-id2", 44 }, 45 }, 46 }, 47 { 48 description: "request with imps and stored bid response for both of these imp", 49 reqIn: &openrtb2.BidRequest{Imp: []openrtb2.Imp{ 50 {ID: "imp-id1"}, 51 {ID: "imp-id2"}, 52 }}, 53 storedBidResponses: ImpBidderStoredResp{ 54 "imp-id1": {"appnexus": bidRespId1}, 55 "imp-id2": {"appnexus": bidRespId1}, 56 }, 57 expectedImps: nil, 58 }, 59 { 60 description: "request with imps and no stored bid responses", 61 reqIn: &openrtb2.BidRequest{Imp: []openrtb2.Imp{ 62 {ID: "imp-id1"}, 63 {ID: "imp-id2"}, 64 }}, 65 storedBidResponses: nil, 66 67 expectedImps: []openrtb2.Imp{ 68 {ID: "imp-id1"}, 69 {ID: "imp-id2"}, 70 }, 71 }, 72 } 73 for _, testCase := range testCases { 74 request := testCase.reqIn 75 removeImpsWithStoredResponses(request, testCase.storedBidResponses) 76 assert.Equal(t, testCase.expectedImps, request.Imp, "incorrect Impressions for testCase %s", testCase.description) 77 } 78 } 79 80 func TestBuildStoredBidResponses(t *testing.T) { 81 bidRespId1 := json.RawMessage(`{"id": "resp_id1"}`) 82 bidRespId2 := json.RawMessage(`{"id": "resp_id2"}`) 83 bidRespId3 := json.RawMessage(`{"id": "resp_id3"}`) 84 testCases := []struct { 85 description string 86 storedBidResponses ImpBidderStoredResp 87 expectedResult BidderImpsWithBidResponses 88 }{ 89 { 90 description: "one imp and stored response for this imp with one bidder", 91 storedBidResponses: ImpBidderStoredResp{ 92 "imp-id1": {"bidderA": bidRespId1}, 93 }, 94 expectedResult: BidderImpsWithBidResponses{ 95 "bidderA": { 96 "imp-id1": bidRespId1, 97 }, 98 }, 99 }, 100 { 101 description: "one imp and stored response for this imp with two bidders", 102 storedBidResponses: ImpBidderStoredResp{ 103 "imp-id1": {"bidderA": bidRespId1, "bidderB": bidRespId2}, 104 }, 105 106 expectedResult: BidderImpsWithBidResponses{ 107 "bidderA": { 108 "imp-id1": bidRespId1, 109 }, 110 "bidderB": { 111 "imp-id1": bidRespId2, 112 }, 113 }, 114 }, 115 { 116 description: "two imps and stored response for this imp with two bidders", 117 storedBidResponses: ImpBidderStoredResp{ 118 "imp-id1": {"bidderA": bidRespId1}, 119 "imp-id2": {"bidderB": bidRespId2}, 120 }, 121 122 expectedResult: BidderImpsWithBidResponses{ 123 "bidderA": { 124 "imp-id1": bidRespId1, 125 }, 126 "bidderB": { 127 "imp-id2": bidRespId2, 128 }, 129 }, 130 }, 131 { 132 description: "three imps and stored response for these imps with two bidders", 133 storedBidResponses: ImpBidderStoredResp{ 134 "imp-id1": {"bidderA": bidRespId1}, 135 "imp-id2": {"bidderB": bidRespId2}, 136 "imp-id3": {"bidderA": bidRespId3}, 137 }, 138 139 expectedResult: BidderImpsWithBidResponses{ 140 "bidderA": { 141 "imp-id1": bidRespId1, 142 "imp-id3": bidRespId3, 143 }, 144 "bidderB": { 145 "imp-id2": bidRespId2, 146 }, 147 }, 148 }, 149 { 150 description: "empty stored responses", 151 storedBidResponses: ImpBidderStoredResp{}, 152 expectedResult: BidderImpsWithBidResponses{}, 153 }, 154 } 155 156 for _, testCase := range testCases { 157 158 bidderToImpToResponses := buildStoredResp(testCase.storedBidResponses) 159 for expectedBidderName := range testCase.expectedResult { 160 assert.Equal(t, testCase.expectedResult[expectedBidderName], bidderToImpToResponses[expectedBidderName], "incorrect stored responses for testCase %s", testCase.description) 161 } 162 } 163 } 164 165 func TestProcessStoredAuctionAndBidResponsesErrors(t *testing.T) { 166 bidderMap := map[string]openrtb_ext.BidderName{"testBidder": "testBidder"} 167 168 testCases := []struct { 169 description string 170 requestJson []byte 171 expectedErrorList []error 172 }{ 173 { 174 description: "Invalid stored auction response format: empty stored Auction Response Id", 175 requestJson: []byte(`{"imp": [ 176 { 177 "id": "imp-id1", 178 "ext": { 179 "prebid": { 180 "storedauctionresponse": { 181 } 182 } 183 } 184 } 185 ]}`), 186 expectedErrorList: []error{errors.New("request.imp[0] has ext.prebid.storedauctionresponse specified, but \"id\" field is missing ")}, 187 }, 188 { 189 description: "Invalid stored bid response format: empty storedbidresponse.bidder", 190 requestJson: []byte(`{"imp": [ 191 { 192 "id": "imp-id1", 193 "ext": { 194 "prebid": { 195 "storedbidresponse": [ 196 { "id": "123abc"}] 197 } 198 } 199 } 200 ]}`), 201 expectedErrorList: []error{errors.New("request.imp[0] has ext.prebid.storedbidresponse specified, but \"id\" or/and \"bidder\" fields are missing ")}, 202 }, 203 { 204 description: "Invalid stored bid response format: empty storedbidresponse.id", 205 requestJson: []byte(`{"imp": [ 206 { 207 "id": "imp-id1", 208 "ext": { 209 "prebid": { 210 "storedbidresponse": [ 211 { "bidder": "testbidder"}] 212 } 213 } 214 } 215 ]}`), 216 expectedErrorList: []error{errors.New("request.imp[0] has ext.prebid.storedbidresponse specified, but \"id\" or/and \"bidder\" fields are missing ")}, 217 }, 218 { 219 description: "Invalid stored bid response: storedbidresponse.bidder not found", 220 requestJson: []byte(`{"imp": [ 221 { 222 "id": "imp-id1", 223 "ext": { 224 "prebid": { 225 "storedbidresponse": [ 226 { "bidder": "testBidder123", "id": "123abc"}] 227 } 228 } 229 } 230 ]}`), 231 expectedErrorList: []error{errors.New("request.imp[impId: imp-id1].ext.prebid.bidder contains unknown bidder: testBidder123. Did you forget an alias in request.ext.prebid.aliases?")}, 232 }, 233 { 234 description: "Invalid stored auction response format: empty stored Auction Response Id in second imp", 235 requestJson: []byte(`{"imp": [ 236 { 237 "id": "imp-id1", 238 "ext": { 239 "prebid": { 240 "storedauctionresponse": { 241 "id":"123" 242 } 243 } 244 } 245 }, 246 { 247 "id": "imp-id2", 248 "ext": { 249 "prebid": { 250 "storedauctionresponse": { 251 "id":"" 252 } 253 } 254 } 255 } 256 ]}`), 257 expectedErrorList: []error{errors.New("request.imp[1] has ext.prebid.storedauctionresponse specified, but \"id\" field is missing ")}, 258 }, 259 { 260 description: "Invalid stored bid response format: empty stored bid Response Id in second imp", 261 requestJson: []byte(`{"imp": [ 262 { 263 "id": "imp-id1", 264 "ext": { 265 "prebid": { 266 "storedbidresponse": [ 267 {"bidder":"testBidder", "id": "123abc"} 268 ] 269 } 270 } 271 }, 272 { 273 "id": "imp-id2", 274 "ext": { 275 "prebid": { 276 "storedbidresponse": [ 277 {"bidder":"testBidder", "id": ""} 278 ] 279 } 280 } 281 } 282 ]}`), 283 expectedErrorList: []error{errors.New("request.imp[1] has ext.prebid.storedbidresponse specified, but \"id\" or/and \"bidder\" fields are missing ")}, 284 }, 285 } 286 287 for _, test := range testCases { 288 _, _, _, errorList := ProcessStoredResponses(nil, test.requestJson, nil, bidderMap) 289 assert.Equalf(t, test.expectedErrorList, errorList, "Error doesn't match: %s\n", test.description) 290 } 291 292 } 293 294 func TestProcessStoredAuctionAndBidResponses(t *testing.T) { 295 bidderMap := map[string]openrtb_ext.BidderName{"bidderA": "bidderA", "bidderB": "bidderB"} 296 bidStoredResp1 := json.RawMessage(`[{"bid": [{"id": "bid_id1"],"seat": "bidderA"}]`) 297 bidStoredResp2 := json.RawMessage(`[{"bid": [{"id": "bid_id2"],"seat": "bidderB"}]`) 298 bidStoredResp3 := json.RawMessage(`[{"bid": [{"id": "bid_id3"],"seat": "bidderA"}]`) 299 mockStoredResponses := map[string]json.RawMessage{ 300 "1": bidStoredResp1, 301 "2": bidStoredResp2, 302 "3": bidStoredResp3, 303 } 304 fetcher := &mockStoredBidResponseFetcher{mockStoredResponses} 305 306 testCases := []struct { 307 description string 308 requestJson []byte 309 expectedStoredAuctionResponses ImpsWithBidResponses 310 expectedStoredBidResponses ImpBidderStoredResp 311 expectedBidderImpReplaceImpID BidderImpReplaceImpID 312 }{ 313 { 314 description: "No stored responses", 315 requestJson: []byte(`{"imp": [ 316 { 317 "id": "imp-id1", 318 "ext": { 319 "prebid": { 320 321 } 322 } 323 } 324 ]}`), 325 expectedStoredAuctionResponses: nil, 326 expectedStoredBidResponses: nil, 327 expectedBidderImpReplaceImpID: nil, 328 }, 329 { 330 description: "Stored auction response one imp", 331 requestJson: []byte(`{"imp": [ 332 { 333 "id": "imp-id1", 334 "ext": { 335 "appnexus": { 336 "placementId": 123 337 }, 338 "prebid": { 339 "storedauctionresponse": { 340 "id": "1" 341 } 342 } 343 } 344 } 345 ]}`), 346 expectedStoredAuctionResponses: ImpsWithBidResponses{ 347 "imp-id1": bidStoredResp1, 348 }, 349 expectedStoredBidResponses: ImpBidderStoredResp{}, 350 expectedBidderImpReplaceImpID: BidderImpReplaceImpID{}, 351 }, 352 { 353 description: "Stored bid response one imp", 354 requestJson: []byte(`{"imp": [ 355 { 356 "id": "imp-id1", 357 "ext": { 358 "appnexus": { 359 "placementId": 123 360 }, 361 "prebid": { 362 "storedbidresponse": [ 363 {"bidder":"bidderA", "id": "1"} 364 ] 365 } 366 } 367 } 368 ]}`), 369 expectedStoredAuctionResponses: ImpsWithBidResponses{}, 370 expectedStoredBidResponses: ImpBidderStoredResp{ 371 "imp-id1": {"bidderA": bidStoredResp1}, 372 }, 373 expectedBidderImpReplaceImpID: BidderImpReplaceImpID{ 374 "bidderA": map[string]bool{"imp-id1": true}, 375 }, 376 }, 377 { 378 description: "Stored bid responses two bidders one imp", 379 requestJson: []byte(`{"imp": [ 380 { 381 "id": "imp-id1", 382 "ext": { 383 "appnexus": { 384 "placementId": 123 385 }, 386 "prebid": { 387 "storedbidresponse": [ 388 {"bidder":"bidderA", "id": "1", "replaceimpid": true}, 389 {"bidder":"bidderB", "id": "2", "replaceimpid": false} 390 ] 391 } 392 } 393 } 394 ]}`), 395 expectedStoredAuctionResponses: ImpsWithBidResponses{}, 396 expectedStoredBidResponses: ImpBidderStoredResp{ 397 "imp-id1": {"bidderA": bidStoredResp1, "bidderB": bidStoredResp2}, 398 }, 399 expectedBidderImpReplaceImpID: BidderImpReplaceImpID{ 400 "bidderA": map[string]bool{"imp-id1": true}, 401 "bidderB": map[string]bool{"imp-id1": false}, 402 }, 403 }, 404 { 405 //This is not a valid scenario for real auction request, added for testing purposes 406 description: "Stored auction and bid responses one imp", 407 requestJson: []byte(`{"imp": [ 408 { 409 "id": "imp-id1", 410 "ext": { 411 "appnexus": { 412 "placementId": 123 413 }, 414 "prebid": { 415 "storedauctionresponse": { 416 "id": "1" 417 }, 418 "storedbidresponse": [ 419 {"bidder":"bidderA", "id": "1"}, 420 {"bidder":"bidderB", "id": "2"} 421 ] 422 } 423 } 424 } 425 ]}`), 426 expectedStoredAuctionResponses: ImpsWithBidResponses{ 427 "imp-id1": bidStoredResp1, 428 }, 429 expectedStoredBidResponses: ImpBidderStoredResp{ 430 "imp-id1": {"bidderA": bidStoredResp1, "bidderB": bidStoredResp2}, 431 }, 432 expectedBidderImpReplaceImpID: BidderImpReplaceImpID{ 433 "bidderA": map[string]bool{"imp-id1": true}, 434 "bidderB": map[string]bool{"imp-id1": true}, 435 }, 436 }, 437 { 438 description: "Stored auction response three imps", 439 requestJson: []byte(`{"imp": [ 440 { 441 "id": "imp-id1", 442 "ext": { 443 "appnexus": { 444 "placementId": 123 445 }, 446 "prebid": { 447 "storedauctionresponse": { 448 "id": "1" 449 } 450 } 451 } 452 }, 453 { 454 "id": "imp-id2", 455 "ext": { 456 "appnexus": { 457 "placementId": 123 458 }, 459 "prebid": { 460 "storedauctionresponse": { 461 "id": "2" 462 } 463 } 464 } 465 }, 466 { 467 "id": "imp-id3", 468 "ext": { 469 "appnexus": { 470 "placementId": 123 471 }, 472 "prebid": { 473 "storedauctionresponse": { 474 "id": "3" 475 } 476 } 477 } 478 } 479 ]}`), 480 expectedStoredAuctionResponses: ImpsWithBidResponses{ 481 "imp-id1": bidStoredResp1, 482 "imp-id2": bidStoredResp2, 483 "imp-id3": bidStoredResp3, 484 }, 485 expectedStoredBidResponses: ImpBidderStoredResp{}, 486 expectedBidderImpReplaceImpID: BidderImpReplaceImpID{}, 487 }, 488 { 489 description: "Stored auction response three imps duplicated stored auction response", 490 requestJson: []byte(`{"imp": [ 491 { 492 "id": "imp-id1", 493 "ext": { 494 "appnexus": { 495 "placementId": 123 496 }, 497 "prebid": { 498 "storedauctionresponse": { 499 "id": "1" 500 } 501 } 502 } 503 }, 504 { 505 "id": "imp-id2", 506 "ext": { 507 "appnexus": { 508 "placementId": 123 509 }, 510 "prebid": { 511 "storedauctionresponse": { 512 "id": "2" 513 } 514 } 515 } 516 }, 517 { 518 "id": "imp-id3", 519 "ext": { 520 "appnexus": { 521 "placementId": 123 522 }, 523 "prebid": { 524 "storedauctionresponse": { 525 "id": "2" 526 } 527 } 528 } 529 } 530 ]}`), 531 expectedStoredAuctionResponses: ImpsWithBidResponses{ 532 "imp-id1": bidStoredResp1, 533 "imp-id2": bidStoredResp2, 534 "imp-id3": bidStoredResp2, 535 }, 536 expectedStoredBidResponses: ImpBidderStoredResp{}, 537 expectedBidderImpReplaceImpID: BidderImpReplaceImpID{}, 538 }, 539 { 540 description: "Stored bid responses two bidders two imp", 541 requestJson: []byte(`{"imp": [ 542 { 543 "id": "imp-id1", 544 "ext": { 545 "appnexus": { 546 "placementId": 123 547 }, 548 "prebid": { 549 "storedbidresponse": [ 550 {"bidder":"bidderA", "id": "1", "replaceimpid": false}, 551 {"bidder":"bidderB", "id": "2"} 552 ] 553 } 554 } 555 }, 556 { 557 "id": "imp-id2", 558 "ext": { 559 "appnexus": { 560 "placementId": 123 561 }, 562 "prebid": { 563 "storedbidresponse": [ 564 {"bidder":"bidderA", "id": "3"}, 565 {"bidder":"bidderB", "id": "2", "replaceimpid": false} 566 ] 567 } 568 } 569 } 570 ]}`), 571 expectedStoredAuctionResponses: ImpsWithBidResponses{}, 572 expectedStoredBidResponses: ImpBidderStoredResp{ 573 "imp-id1": {"bidderA": bidStoredResp1, "bidderB": bidStoredResp2}, 574 "imp-id2": {"bidderA": bidStoredResp3, "bidderB": bidStoredResp2}, 575 }, 576 expectedBidderImpReplaceImpID: BidderImpReplaceImpID{ 577 "bidderA": map[string]bool{"imp-id1": false, "imp-id2": true}, 578 "bidderB": map[string]bool{"imp-id1": true, "imp-id2": false}, 579 }, 580 }, 581 } 582 583 for _, test := range testCases { 584 storedAuctionResponses, storedBidResponses, bidderImpReplaceImpId, errorList := ProcessStoredResponses(nil, test.requestJson, fetcher, bidderMap) 585 assert.Equal(t, test.expectedStoredAuctionResponses, storedAuctionResponses, "storedAuctionResponses doesn't match: %s\n", test.description) 586 assert.Equalf(t, test.expectedStoredBidResponses, storedBidResponses, "storedBidResponses doesn't match: %s\n", test.description) 587 assert.Equal(t, test.expectedBidderImpReplaceImpID, bidderImpReplaceImpId, "bidderImpReplaceImpId doesn't match: %s\n", test.description) 588 assert.Nil(t, errorList, "Error should be nil") 589 } 590 591 } 592 593 func TestProcessStoredResponsesNotFoundResponse(t *testing.T) { 594 bidderMap := map[string]openrtb_ext.BidderName{"bidderA": "bidderA", "bidderB": "bidderB"} 595 bidStoredResp1 := json.RawMessage(`[{"bid": [{"id": "bid_id1"],"seat": "bidderA"}]`) 596 bidStoredResp2 := json.RawMessage(`[{"bid": [{"id": "bid_id2"],"seat": "bidderB"}]`) 597 mockStoredResponses := map[string]json.RawMessage{ 598 "1": bidStoredResp1, 599 "2": bidStoredResp2, 600 "3": nil, 601 "4": nil, 602 } 603 fetcher := &mockStoredBidResponseFetcher{mockStoredResponses} 604 605 testCases := []struct { 606 description string 607 requestJson []byte 608 expectedErrors []error 609 }{ 610 { 611 description: "Stored bid response with nil data, one bidder one imp", 612 requestJson: []byte(`{"imp": [ 613 { 614 "id": "imp-id1", 615 "ext": { 616 "appnexus": { 617 "placementId": 123 618 }, 619 "prebid": { 620 "storedbidresponse": [ 621 {"bidder":"bidderB", "id": "3"} 622 ] 623 } 624 } 625 } 626 ]}`), 627 expectedErrors: []error{ 628 errors.New("failed to fetch stored bid response for impId = imp-id1, bidder = bidderB and storedBidResponse id = 3"), 629 }, 630 }, 631 { 632 description: "Stored bid response with nil data, one bidder, two imps, one with correct stored response", 633 requestJson: []byte(`{"imp": [ 634 { 635 "id": "imp-id1", 636 "ext": { 637 "appnexus": { 638 "placementId": 123 639 }, 640 "prebid": { 641 "storedbidresponse": [ 642 {"bidder":"bidderB", "id": "1"} 643 ] 644 } 645 } 646 }, 647 { 648 "id": "imp-id2", 649 "ext": { 650 "appnexus": { 651 "placementId": 123 652 }, 653 "prebid": { 654 "storedbidresponse": [ 655 {"bidder":"bidderB", "id": "3"} 656 ] 657 } 658 } 659 } 660 ]}`), 661 expectedErrors: []error{ 662 errors.New("failed to fetch stored bid response for impId = imp-id2, bidder = bidderB and storedBidResponse id = 3"), 663 }, 664 }, 665 { 666 description: "Stored bid response with nil data, one bidder, two imps, both with correct stored response", 667 requestJson: []byte(`{"imp": [ 668 { 669 "id": "imp-id1", 670 "ext": { 671 "appnexus": { 672 "placementId": 123 673 }, 674 "prebid": { 675 "storedbidresponse": [ 676 {"bidder":"bidderB", "id": "4"} 677 ] 678 } 679 } 680 }, 681 { 682 "id": "imp-id2", 683 "ext": { 684 "appnexus": { 685 "placementId": 123 686 }, 687 "prebid": { 688 "storedbidresponse": [ 689 {"bidder":"bidderB", "id": "3"} 690 ] 691 } 692 } 693 } 694 ]}`), 695 expectedErrors: []error{ 696 errors.New("failed to fetch stored bid response for impId = imp-id1, bidder = bidderB and storedBidResponse id = 4"), 697 errors.New("failed to fetch stored bid response for impId = imp-id2, bidder = bidderB and storedBidResponse id = 3"), 698 }, 699 }, 700 { 701 description: "Stored auction response with nil data and one imp", 702 requestJson: []byte(`{"imp": [ 703 { 704 "id": "imp-id1", 705 "ext": { 706 "appnexus": { 707 "placementId": 123 708 }, 709 "prebid": { 710 "storedauctionresponse": { 711 "id": "4" 712 } 713 } 714 } 715 } 716 ]}`), 717 expectedErrors: []error{ 718 errors.New("failed to fetch stored auction response for impId = imp-id1 and storedAuctionResponse id = 4"), 719 }, 720 }, 721 { 722 description: "Stored auction response with nil data, and two imps with nil responses", 723 requestJson: []byte(`{"imp": [ 724 { 725 "id": "imp-id1", 726 "ext": { 727 "appnexus": { 728 "placementId": 123 729 }, 730 "prebid": { 731 "storedauctionresponse": { 732 "id": "4" 733 } 734 } 735 } 736 }, 737 { 738 "id": "imp-id2", 739 "ext": { 740 "appnexus": { 741 "placementId": 123 742 }, 743 "prebid": { 744 "storedauctionresponse": { 745 "id": "3" 746 } 747 } 748 } 749 } 750 ]}`), 751 expectedErrors: []error{ 752 errors.New("failed to fetch stored auction response for impId = imp-id1 and storedAuctionResponse id = 4"), 753 errors.New("failed to fetch stored auction response for impId = imp-id2 and storedAuctionResponse id = 3"), 754 }, 755 }, 756 { 757 description: "Stored auction response with nil data, two imps, one with nil responses", 758 requestJson: []byte(`{"imp": [ 759 { 760 "id": "imp-id1", 761 "ext": { 762 "appnexus": { 763 "placementId": 123 764 }, 765 "prebid": { 766 "storedauctionresponse": { 767 "id": "2" 768 } 769 } 770 } 771 }, 772 { 773 "id": "imp-id2", 774 "ext": { 775 "appnexus": { 776 "placementId": 123 777 }, 778 "prebid": { 779 "storedauctionresponse": { 780 "id": "3" 781 } 782 } 783 } 784 } 785 ]}`), 786 expectedErrors: []error{ 787 errors.New("failed to fetch stored auction response for impId = imp-id2 and storedAuctionResponse id = 3"), 788 }, 789 }, 790 } 791 792 for _, test := range testCases { 793 _, _, _, errorList := ProcessStoredResponses(nil, test.requestJson, fetcher, bidderMap) 794 for _, err := range test.expectedErrors { 795 assert.Contains(t, errorList, err, "incorrect errors returned: %s", test.description) 796 } 797 } 798 } 799 800 func TestFlipMap(t *testing.T) { 801 testCases := []struct { 802 description string 803 inImpBidderReplaceImpID ImpBidderReplaceImpID 804 outBidderImpReplaceImpID BidderImpReplaceImpID 805 }{ 806 { 807 description: "Empty ImpBidderReplaceImpID", 808 inImpBidderReplaceImpID: ImpBidderReplaceImpID{}, 809 outBidderImpReplaceImpID: BidderImpReplaceImpID{}, 810 }, 811 { 812 description: "Nil ImpBidderReplaceImpID", 813 inImpBidderReplaceImpID: nil, 814 outBidderImpReplaceImpID: BidderImpReplaceImpID{}, 815 }, 816 { 817 description: "ImpBidderReplaceImpID has a one element map with single element", 818 inImpBidderReplaceImpID: ImpBidderReplaceImpID{"imp-id": {"bidderA": true}}, 819 outBidderImpReplaceImpID: BidderImpReplaceImpID{"bidderA": {"imp-id": true}}, 820 }, 821 { 822 description: "ImpBidderReplaceImpID has a one element map with multiple elements", 823 inImpBidderReplaceImpID: ImpBidderReplaceImpID{"imp-id": {"bidderA": true, "bidderB": false}}, 824 outBidderImpReplaceImpID: BidderImpReplaceImpID{"bidderA": {"imp-id": true}, "bidderB": {"imp-id": false}}, 825 }, 826 { 827 description: "ImpBidderReplaceImpID has multiple elements map with single element", 828 inImpBidderReplaceImpID: ImpBidderReplaceImpID{ 829 "imp-id1": {"bidderA": true}, 830 "imp-id2": {"bidderB": false}}, 831 outBidderImpReplaceImpID: BidderImpReplaceImpID{ 832 "bidderA": {"imp-id1": true}, 833 "bidderB": {"imp-id2": false}}, 834 }, 835 { 836 description: "ImpBidderReplaceImpID has multiple elements map with multiple elements", 837 inImpBidderReplaceImpID: ImpBidderReplaceImpID{ 838 "imp-id1": {"bidderA": true, "bidderB": false, "bidderC": false, "bidderD": true}, 839 "imp-id2": {"bidderA": false, "bidderB": false, "bidderC": true, "bidderD": true}, 840 "imp-id3": {"bidderA": false, "bidderB": true, "bidderC": true, "bidderD": false}}, 841 outBidderImpReplaceImpID: BidderImpReplaceImpID{ 842 "bidderA": {"imp-id1": true, "imp-id2": false, "imp-id3": false}, 843 "bidderB": {"imp-id1": false, "imp-id2": false, "imp-id3": true}, 844 "bidderC": {"imp-id1": false, "imp-id2": true, "imp-id3": true}, 845 "bidderD": {"imp-id1": true, "imp-id2": true, "imp-id3": false}}, 846 }, 847 } 848 849 for _, test := range testCases { 850 actualResult := flipMap(test.inImpBidderReplaceImpID) 851 assert.Equal(t, test.outBidderImpReplaceImpID, actualResult, "Incorrect flipped map for test case %s\n", test.description) 852 } 853 } 854 855 type mockStoredBidResponseFetcher struct { 856 data map[string]json.RawMessage 857 } 858 859 func (cf *mockStoredBidResponseFetcher) FetchRequests(ctx context.Context, requestIDs []string, impIDs []string) (requestData map[string]json.RawMessage, impData map[string]json.RawMessage, errs []error) { 860 return nil, nil, nil 861 } 862 863 func (cf *mockStoredBidResponseFetcher) FetchResponses(ctx context.Context, ids []string) (data map[string]json.RawMessage, errs []error) { 864 return cf.data, nil 865 }