github.com/prebid/prebid-server@v0.275.0/config/bidderinfo_test.go (about) 1 package config 2 3 import ( 4 "errors" 5 "strings" 6 "testing" 7 8 "gopkg.in/yaml.v3" 9 10 "github.com/prebid/prebid-server/openrtb_ext" 11 "github.com/stretchr/testify/assert" 12 ) 13 14 const testInfoFilesPathValid = "./test/bidder-info-valid" 15 const testSimpleYAML = ` 16 maintainer: 17 email: some-email@domain.com 18 gvlVendorID: 42 19 ` 20 const fullBidderYAMLConfig = ` 21 maintainer: 22 email: some-email@domain.com 23 capabilities: 24 app: 25 mediaTypes: 26 - banner 27 - video 28 - native 29 site: 30 mediaTypes: 31 - banner 32 - video 33 - native 34 modifyingVastXmlAllowed: true 35 debug: 36 allow: true 37 gvlVendorID: 42 38 experiment: 39 adsCert: 40 enabled: true 41 endpointCompression: GZIP 42 openrtb: 43 version: 2.6 44 gpp-supported: true 45 endpoint: https://endpoint.com 46 disabled: false 47 extra_info: extra-info 48 app_secret: app-secret 49 platform_id: 123 50 usersync_url: user-url 51 userSync: 52 key: foo 53 default: iframe 54 iframe: 55 url: https://foo.com/sync?mode=iframe&r={{.RedirectURL}} 56 redirectUrl: https://redirect/setuid/iframe 57 externalUrl: https://iframe.host 58 userMacro: UID 59 xapi: 60 username: uname 61 password: pwd 62 tracker: tracker 63 ` 64 const testSimpleAliasYAML = ` 65 aliasOf: bidderA 66 ` 67 68 func TestLoadBidderInfoFromDisk(t *testing.T) { 69 // should appear in result in mixed case 70 bidder := "stroeerCore" 71 trueValue := true 72 73 adapterConfigs := make(map[string]Adapter) 74 adapterConfigs[strings.ToLower(bidder)] = Adapter{} 75 76 infos, err := LoadBidderInfoFromDisk(testInfoFilesPathValid) 77 if err != nil { 78 t.Fatal(err) 79 } 80 81 expected := BidderInfos{ 82 bidder: { 83 Disabled: false, 84 Maintainer: &MaintainerInfo{ 85 Email: "some-email@domain.com", 86 }, 87 GVLVendorID: 42, 88 Capabilities: &CapabilitiesInfo{ 89 App: &PlatformInfo{ 90 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeNative}, 91 }, 92 Site: &PlatformInfo{ 93 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative}, 94 }, 95 }, 96 Syncer: &Syncer{ 97 Key: "foo", 98 IFrame: &SyncerEndpoint{ 99 URL: "https://foo.com/sync?mode=iframe&r={{.RedirectURL}}", 100 RedirectURL: "{{.ExternalURL}}/setuid/iframe", 101 ExternalURL: "https://iframe.host", 102 UserMacro: "%UID", 103 }, 104 Redirect: &SyncerEndpoint{ 105 URL: "https://foo.com/sync?mode=redirect&r={{.RedirectURL}}", 106 RedirectURL: "{{.ExternalURL}}/setuid/redirect", 107 ExternalURL: "https://redirect.host", 108 UserMacro: "#UID", 109 }, 110 SupportCORS: &trueValue, 111 }, 112 }, 113 } 114 assert.Equal(t, expected, infos) 115 } 116 117 func TestProcessBidderInfo(t *testing.T) { 118 testCases := []struct { 119 description string 120 bidderInfos map[string][]byte 121 expectedBidderInfos BidderInfos 122 expectError string 123 }{ 124 { 125 description: "Valid bidder info", 126 bidderInfos: map[string][]byte{ 127 "bidderA.yaml": []byte(testSimpleYAML), 128 }, 129 expectedBidderInfos: BidderInfos{ 130 "bidderA": BidderInfo{ 131 Maintainer: &MaintainerInfo{ 132 Email: "some-email@domain.com", 133 }, 134 GVLVendorID: 42, 135 }, 136 }, 137 expectError: "", 138 }, 139 { 140 description: "Bidder doesn't exist in bidder info list", 141 bidderInfos: map[string][]byte{ 142 "unknown.yaml": []byte(testSimpleYAML), 143 }, 144 expectedBidderInfos: nil, 145 expectError: "error parsing config for bidder unknown.yaml", 146 }, 147 { 148 description: "Invalid bidder config", 149 bidderInfos: map[string][]byte{ 150 "bidderA.yaml": []byte("invalid bidder config"), 151 }, 152 expectedBidderInfos: nil, 153 expectError: "error parsing config for bidder bidderA.yaml", 154 }, 155 { 156 description: "Invalid alias name", 157 bidderInfos: map[string][]byte{ 158 "all.yaml": []byte(testSimpleAliasYAML), 159 }, 160 expectedBidderInfos: nil, 161 expectError: "alias all is a reserved bidder name and cannot be used", 162 }, 163 { 164 description: "Valid aliases", 165 bidderInfos: map[string][]byte{ 166 "bidderA.yaml": []byte(fullBidderYAMLConfig), 167 "bidderB.yaml": []byte(testSimpleAliasYAML), 168 }, 169 expectedBidderInfos: BidderInfos{ 170 "bidderA": BidderInfo{ 171 AppSecret: "app-secret", 172 Capabilities: &CapabilitiesInfo{ 173 App: &PlatformInfo{ 174 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative}, 175 }, 176 Site: &PlatformInfo{ 177 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative}, 178 }, 179 }, 180 Debug: &DebugInfo{ 181 Allow: true, 182 }, 183 Disabled: false, 184 Endpoint: "https://endpoint.com", 185 EndpointCompression: "GZIP", 186 Experiment: BidderInfoExperiment{ 187 AdsCert: BidderAdsCert{ 188 Enabled: true, 189 }, 190 }, 191 ExtraAdapterInfo: "extra-info", 192 GVLVendorID: 42, 193 Maintainer: &MaintainerInfo{ 194 Email: "some-email@domain.com", 195 }, 196 ModifyingVastXmlAllowed: true, 197 OpenRTB: &OpenRTBInfo{ 198 GPPSupported: true, 199 Version: "2.6", 200 }, 201 PlatformID: "123", 202 Syncer: &Syncer{ 203 Key: "foo", 204 IFrame: &SyncerEndpoint{ 205 URL: "https://foo.com/sync?mode=iframe&r={{.RedirectURL}}", 206 RedirectURL: "https://redirect/setuid/iframe", 207 ExternalURL: "https://iframe.host", 208 UserMacro: "UID", 209 }, 210 }, 211 UserSyncURL: "user-url", 212 XAPI: AdapterXAPI{ 213 Username: "uname", 214 Password: "pwd", 215 Tracker: "tracker", 216 }, 217 }, 218 "bidderB": BidderInfo{ 219 AliasOf: "bidderA", 220 AppSecret: "app-secret", 221 Capabilities: &CapabilitiesInfo{ 222 App: &PlatformInfo{ 223 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative}, 224 }, 225 Site: &PlatformInfo{ 226 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative}, 227 }, 228 }, 229 Debug: &DebugInfo{ 230 Allow: true, 231 }, 232 Disabled: false, 233 Endpoint: "https://endpoint.com", 234 EndpointCompression: "GZIP", 235 Experiment: BidderInfoExperiment{ 236 AdsCert: BidderAdsCert{ 237 Enabled: true, 238 }, 239 }, 240 ExtraAdapterInfo: "extra-info", 241 GVLVendorID: 42, 242 Maintainer: &MaintainerInfo{ 243 Email: "some-email@domain.com", 244 }, 245 ModifyingVastXmlAllowed: true, 246 OpenRTB: &OpenRTBInfo{ 247 GPPSupported: true, 248 Version: "2.6", 249 }, 250 PlatformID: "123", 251 Syncer: &Syncer{ 252 Key: "foo", 253 IFrame: &SyncerEndpoint{ 254 URL: "https://foo.com/sync?mode=iframe&r={{.RedirectURL}}", 255 RedirectURL: "https://redirect/setuid/iframe", 256 ExternalURL: "https://iframe.host", 257 UserMacro: "UID", 258 }, 259 }, 260 UserSyncURL: "user-url", 261 XAPI: AdapterXAPI{ 262 Username: "uname", 263 Password: "pwd", 264 Tracker: "tracker", 265 }, 266 }, 267 }, 268 }, 269 } 270 for _, test := range testCases { 271 reader := StubInfoReader{test.bidderInfos} 272 bidderInfos, err := processBidderInfos(reader, mockNormalizeBidderName) 273 if test.expectError != "" { 274 assert.ErrorContains(t, err, test.expectError, "") 275 } else { 276 assert.Equal(t, test.expectedBidderInfos, bidderInfos, "incorrect bidder infos for test case: %s", test.description) 277 } 278 279 } 280 281 } 282 283 func TestProcessAliasBidderInfo(t *testing.T) { 284 parentBidderInfo := BidderInfo{ 285 AppSecret: "app-secret", 286 Capabilities: &CapabilitiesInfo{ 287 App: &PlatformInfo{ 288 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative}, 289 }, 290 Site: &PlatformInfo{ 291 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative}, 292 }, 293 }, 294 Debug: &DebugInfo{ 295 Allow: true, 296 }, 297 Disabled: false, 298 Endpoint: "https://endpoint.com", 299 EndpointCompression: "GZIP", 300 Experiment: BidderInfoExperiment{ 301 AdsCert: BidderAdsCert{ 302 Enabled: true, 303 }, 304 }, 305 ExtraAdapterInfo: "extra-info", 306 GVLVendorID: 42, 307 Maintainer: &MaintainerInfo{ 308 Email: "some-email@domain.com", 309 }, 310 ModifyingVastXmlAllowed: true, 311 OpenRTB: &OpenRTBInfo{ 312 GPPSupported: true, 313 Version: "2.6", 314 }, 315 PlatformID: "123", 316 Syncer: &Syncer{ 317 Key: "foo", 318 IFrame: &SyncerEndpoint{ 319 URL: "https://foo.com/sync?mode=iframe&r={{.RedirectURL}}", 320 RedirectURL: "https://redirect/setuid/iframe", 321 ExternalURL: "https://iframe.host", 322 UserMacro: "UID", 323 }, 324 }, 325 UserSyncURL: "user-url", 326 XAPI: AdapterXAPI{ 327 Username: "uname", 328 Password: "pwd", 329 Tracker: "tracker", 330 }, 331 } 332 aliasBidderInfo := BidderInfo{ 333 AppSecret: "alias-app-secret", 334 Capabilities: &CapabilitiesInfo{ 335 App: &PlatformInfo{ 336 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner}, 337 }, 338 Site: &PlatformInfo{ 339 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner}, 340 }, 341 }, 342 Debug: &DebugInfo{ 343 Allow: false, 344 }, 345 Disabled: true, 346 Endpoint: "https://alias-endpoint.com", 347 EndpointCompression: "DEFAULT", 348 Experiment: BidderInfoExperiment{ 349 AdsCert: BidderAdsCert{ 350 Enabled: false, 351 }, 352 }, 353 ExtraAdapterInfo: "alias-extra-info", 354 GVLVendorID: 43, 355 Maintainer: &MaintainerInfo{ 356 Email: "alias-email@domain.com", 357 }, 358 ModifyingVastXmlAllowed: false, 359 OpenRTB: &OpenRTBInfo{ 360 GPPSupported: false, 361 Version: "2.5", 362 }, 363 PlatformID: "456", 364 Syncer: &Syncer{ 365 Key: "alias", 366 IFrame: &SyncerEndpoint{ 367 URL: "https://alias.com/sync?mode=iframe&r={{.RedirectURL}}", 368 RedirectURL: "https://alias-redirect/setuid/iframe", 369 ExternalURL: "https://alias-iframe.host", 370 UserMacro: "alias-UID", 371 }, 372 }, 373 UserSyncURL: "alias-user-url", 374 XAPI: AdapterXAPI{ 375 Username: "alias-uname", 376 Password: "alias-pwd", 377 Tracker: "alias-tracker", 378 }, 379 } 380 bidderB := parentBidderInfo 381 bidderB.AliasOf = "bidderA" 382 testCases := []struct { 383 description string 384 aliasInfos map[string]aliasNillableFields 385 bidderInfos BidderInfos 386 expectedBidderInfos BidderInfos 387 expectedErr error 388 }{ 389 { 390 description: "inherit all parent info in alias bidder", 391 aliasInfos: map[string]aliasNillableFields{ 392 "bidderB": { 393 Disabled: nil, 394 ModifyingVastXmlAllowed: nil, 395 Experiment: nil, 396 XAPI: nil, 397 }, 398 }, 399 bidderInfos: BidderInfos{ 400 "bidderA": parentBidderInfo, 401 "bidderB": BidderInfo{ 402 AliasOf: "bidderA", 403 // all other fields should be inherited from parent bidder 404 }, 405 }, 406 expectedErr: nil, 407 expectedBidderInfos: BidderInfos{"bidderA": parentBidderInfo, "bidderB": bidderB}, 408 }, 409 { 410 description: "all bidder info specified for alias, do not inherit from parent bidder", 411 aliasInfos: map[string]aliasNillableFields{ 412 "bidderB": { 413 Disabled: &aliasBidderInfo.Disabled, 414 ModifyingVastXmlAllowed: &aliasBidderInfo.ModifyingVastXmlAllowed, 415 Experiment: &aliasBidderInfo.Experiment, 416 XAPI: &aliasBidderInfo.XAPI, 417 }, 418 }, 419 bidderInfos: BidderInfos{ 420 "bidderA": parentBidderInfo, 421 "bidderB": aliasBidderInfo, 422 }, 423 expectedErr: nil, 424 expectedBidderInfos: BidderInfos{"bidderA": parentBidderInfo, "bidderB": aliasBidderInfo}, 425 }, 426 { 427 description: "invalid alias", 428 aliasInfos: map[string]aliasNillableFields{ 429 "bidderB": {}, 430 }, 431 bidderInfos: BidderInfos{ 432 "bidderB": BidderInfo{ 433 AliasOf: "bidderA", 434 }, 435 }, 436 expectedErr: errors.New("bidder: bidderA not found for an alias: bidderB"), 437 }, 438 { 439 description: "bidder info not found for an alias", 440 aliasInfos: map[string]aliasNillableFields{ 441 "bidderB": {}, 442 }, 443 expectedErr: errors.New("bidder info not found for an alias: bidderB"), 444 }, 445 } 446 447 for _, test := range testCases { 448 bidderInfos, err := processBidderAliases(test.aliasInfos, test.bidderInfos) 449 if test.expectedErr != nil { 450 assert.Equal(t, test.expectedErr, err) 451 } else { 452 assert.Equal(t, test.expectedBidderInfos, bidderInfos) 453 } 454 } 455 } 456 457 type StubInfoReader struct { 458 mockBidderInfos map[string][]byte 459 } 460 461 func (r StubInfoReader) Read() (map[string][]byte, error) { 462 return r.mockBidderInfos, nil 463 } 464 465 var testBidderNames = map[string]openrtb_ext.BidderName{ 466 "biddera": openrtb_ext.BidderName("bidderA"), 467 "bidderb": openrtb_ext.BidderName("bidderB"), 468 "bidder1": openrtb_ext.BidderName("bidder1"), 469 "bidder2": openrtb_ext.BidderName("bidder2"), 470 "a": openrtb_ext.BidderName("a"), 471 } 472 473 func mockNormalizeBidderName(name string) (openrtb_ext.BidderName, bool) { 474 nameLower := strings.ToLower(name) 475 bidderName, exists := testBidderNames[nameLower] 476 return bidderName, exists 477 } 478 479 func TestToGVLVendorIDMap(t *testing.T) { 480 givenBidderInfos := BidderInfos{ 481 "bidderA": BidderInfo{Disabled: false, GVLVendorID: 0}, 482 "bidderB": BidderInfo{Disabled: false, GVLVendorID: 100}, 483 "bidderC": BidderInfo{Disabled: true, GVLVendorID: 0}, 484 "bidderD": BidderInfo{Disabled: true, GVLVendorID: 200}, 485 } 486 487 expectedGVLVendorIDMap := map[openrtb_ext.BidderName]uint16{ 488 "bidderB": 100, 489 } 490 491 result := givenBidderInfos.ToGVLVendorIDMap() 492 assert.Equal(t, expectedGVLVendorIDMap, result) 493 } 494 495 const bidderInfoRelativePath = "../static/bidder-info" 496 497 // TestBidderInfoFiles ensures each bidder has a valid static/bidder-info/bidder.yaml file. Validation is performed directly 498 // against the file system with separate yaml unmarshalling from the LoadBidderInfo func. 499 func TestBidderInfoFiles(t *testing.T) { 500 _, err := LoadBidderInfoFromDisk(bidderInfoRelativePath) 501 if err != nil { 502 assert.Fail(t, err.Error(), "Errors in bidder info files") 503 } 504 } 505 506 func TestBidderInfoValidationPositive(t *testing.T) { 507 bidderInfos := BidderInfos{ 508 "bidderA": BidderInfo{ 509 Endpoint: "http://bidderA.com/openrtb2", 510 PlatformID: "A", 511 Maintainer: &MaintainerInfo{ 512 Email: "maintainer@bidderA.com", 513 }, 514 GVLVendorID: 1, 515 Capabilities: &CapabilitiesInfo{ 516 App: &PlatformInfo{ 517 MediaTypes: []openrtb_ext.BidType{ 518 openrtb_ext.BidTypeVideo, 519 openrtb_ext.BidTypeNative, 520 openrtb_ext.BidTypeBanner, 521 }, 522 }, 523 }, 524 Syncer: &Syncer{ 525 Key: "bidderAkey", 526 Redirect: &SyncerEndpoint{ 527 URL: "http://bidderA.com/usersync", 528 UserMacro: "UID", 529 }, 530 }, 531 }, 532 "bidderB": BidderInfo{ 533 Endpoint: "http://bidderB.com/openrtb2", 534 PlatformID: "B", 535 Maintainer: &MaintainerInfo{ 536 Email: "maintainer@bidderA.com", 537 }, 538 GVLVendorID: 2, 539 Capabilities: &CapabilitiesInfo{ 540 Site: &PlatformInfo{ 541 MediaTypes: []openrtb_ext.BidType{ 542 openrtb_ext.BidTypeVideo, 543 openrtb_ext.BidTypeNative, 544 openrtb_ext.BidTypeBanner, 545 }, 546 }, 547 }, 548 Syncer: &Syncer{ 549 Key: "bidderBkey", 550 Redirect: &SyncerEndpoint{ 551 URL: "http://bidderB.com/usersync", 552 UserMacro: "UID", 553 }, 554 }, 555 }, 556 "bidderC": BidderInfo{ 557 Endpoint: "http://bidderB.com/openrtb2", 558 Maintainer: &MaintainerInfo{ 559 Email: "maintainer@bidderA.com", 560 }, 561 Capabilities: &CapabilitiesInfo{ 562 Site: &PlatformInfo{ 563 MediaTypes: []openrtb_ext.BidType{ 564 openrtb_ext.BidTypeVideo, 565 openrtb_ext.BidTypeNative, 566 openrtb_ext.BidTypeBanner, 567 }, 568 }, 569 }, 570 AliasOf: "bidderB", 571 }, 572 } 573 errs := bidderInfos.validate(make([]error, 0)) 574 assert.Len(t, errs, 0, "All bidder infos should be correct") 575 } 576 577 func TestValidateAliases(t *testing.T) { 578 testCase := struct { 579 description string 580 bidderInfos BidderInfos 581 expectErrors []error 582 }{ 583 description: "invalid aliases", 584 bidderInfos: BidderInfos{ 585 "bidderA": BidderInfo{ 586 Endpoint: "http://bidderA.com/openrtb2", 587 Maintainer: &MaintainerInfo{ 588 Email: "maintainer@bidderA.com", 589 }, 590 Capabilities: &CapabilitiesInfo{ 591 Site: &PlatformInfo{ 592 MediaTypes: []openrtb_ext.BidType{ 593 openrtb_ext.BidTypeVideo, 594 }, 595 }, 596 }, 597 AliasOf: "bidderB", 598 }, 599 "bidderB": BidderInfo{ 600 Endpoint: "http://bidderA.com/openrtb2", 601 Maintainer: &MaintainerInfo{ 602 Email: "maintainer@bidderA.com", 603 }, 604 Capabilities: &CapabilitiesInfo{ 605 Site: &PlatformInfo{ 606 MediaTypes: []openrtb_ext.BidType{ 607 openrtb_ext.BidTypeVideo, 608 }, 609 }, 610 }, 611 AliasOf: "bidderC", 612 }, 613 }, 614 expectErrors: []error{ 615 errors.New("bidder: bidderB cannot be an alias of an alias: bidderA"), 616 errors.New("bidder: bidderC not found for an alias: bidderB"), 617 }, 618 } 619 620 var errs []error 621 for bidderName, bidderInfo := range testCase.bidderInfos { 622 errs = append(errs, validateAliases(bidderInfo, testCase.bidderInfos, bidderName)) 623 } 624 625 assert.ElementsMatch(t, errs, testCase.expectErrors) 626 } 627 628 func TestBidderInfoValidationNegative(t *testing.T) { 629 testCases := []struct { 630 description string 631 bidderInfos BidderInfos 632 expectErrors []error 633 }{ 634 { 635 "One bidder incorrect url", 636 BidderInfos{ 637 "bidderA": BidderInfo{ 638 Endpoint: "incorrect", 639 Maintainer: &MaintainerInfo{ 640 Email: "maintainer@bidderA.com", 641 }, 642 Capabilities: &CapabilitiesInfo{ 643 App: &PlatformInfo{ 644 MediaTypes: []openrtb_ext.BidType{ 645 openrtb_ext.BidTypeVideo, 646 }, 647 }, 648 }, 649 }, 650 }, 651 []error{ 652 errors.New("The endpoint: incorrect for bidderA is not a valid URL"), 653 }, 654 }, 655 { 656 "One bidder empty url", 657 BidderInfos{ 658 "bidderA": BidderInfo{ 659 Endpoint: "", 660 Maintainer: &MaintainerInfo{ 661 Email: "maintainer@bidderA.com", 662 }, 663 Capabilities: &CapabilitiesInfo{ 664 App: &PlatformInfo{ 665 MediaTypes: []openrtb_ext.BidType{ 666 openrtb_ext.BidTypeVideo, 667 }, 668 }, 669 }, 670 }, 671 }, 672 []error{ 673 errors.New("There's no default endpoint available for bidderA. Calls to this bidder/exchange will fail. Please set adapters.bidderA.endpoint in your app config"), 674 }, 675 }, 676 { 677 "One bidder incorrect url template", 678 BidderInfos{ 679 "bidderA": BidderInfo{ 680 Endpoint: "http://bidderA.com/openrtb2/getuid?{{.incorrect}}", 681 Maintainer: &MaintainerInfo{ 682 Email: "maintainer@bidderA.com", 683 }, 684 Capabilities: &CapabilitiesInfo{ 685 App: &PlatformInfo{ 686 MediaTypes: []openrtb_ext.BidType{ 687 openrtb_ext.BidTypeVideo, 688 }, 689 }, 690 }, 691 }, 692 }, 693 []error{ 694 errors.New("Unable to resolve endpoint: http://bidderA.com/openrtb2/getuid?{{.incorrect}} for adapter: bidderA. template: endpointTemplate:1:37: executing \"endpointTemplate\" at <.incorrect>: can't evaluate field incorrect in type macros.EndpointTemplateParams"), 695 }, 696 }, 697 { 698 "One bidder incorrect url template parameters", 699 BidderInfos{ 700 "bidderA": BidderInfo{ 701 Endpoint: "http://bidderA.com/openrtb2/getuid?r=[{{.]RedirectURL}}", 702 Maintainer: &MaintainerInfo{ 703 Email: "maintainer@bidderA.com", 704 }, 705 Capabilities: &CapabilitiesInfo{ 706 App: &PlatformInfo{ 707 MediaTypes: []openrtb_ext.BidType{ 708 openrtb_ext.BidTypeVideo, 709 }, 710 }, 711 }, 712 }, 713 }, 714 []error{ 715 errors.New("Invalid endpoint template: http://bidderA.com/openrtb2/getuid?r=[{{.]RedirectURL}} for adapter: bidderA. template: endpointTemplate:1: bad character U+005D ']'"), 716 }, 717 }, 718 { 719 "One bidder no maintainer", 720 BidderInfos{ 721 "bidderA": BidderInfo{ 722 Endpoint: "http://bidderA.com/openrtb2", 723 Capabilities: &CapabilitiesInfo{ 724 App: &PlatformInfo{ 725 MediaTypes: []openrtb_ext.BidType{ 726 openrtb_ext.BidTypeVideo, 727 }, 728 }, 729 }, 730 }, 731 }, 732 []error{ 733 errors.New("missing required field: maintainer.email for adapter: bidderA"), 734 }, 735 }, 736 { 737 "One bidder missing maintainer email", 738 BidderInfos{ 739 "bidderA": BidderInfo{ 740 Endpoint: "http://bidderA.com/openrtb2", 741 Maintainer: &MaintainerInfo{ 742 Email: "", 743 }, 744 Capabilities: &CapabilitiesInfo{ 745 App: &PlatformInfo{ 746 MediaTypes: []openrtb_ext.BidType{ 747 openrtb_ext.BidTypeVideo, 748 }, 749 }, 750 }, 751 }, 752 }, 753 []error{ 754 errors.New("missing required field: maintainer.email for adapter: bidderA"), 755 }, 756 }, 757 { 758 "One bidder missing capabilities", 759 BidderInfos{ 760 "bidderA": BidderInfo{ 761 Endpoint: "http://bidderA.com/openrtb2", 762 Maintainer: &MaintainerInfo{ 763 Email: "maintainer@bidderA.com", 764 }, 765 }, 766 }, 767 []error{ 768 errors.New("missing required field: capabilities for adapter: bidderA"), 769 }, 770 }, 771 { 772 "One bidder missing capabilities site and app", 773 BidderInfos{ 774 "bidderA": BidderInfo{ 775 Endpoint: "http://bidderA.com/openrtb2", 776 Maintainer: &MaintainerInfo{ 777 Email: "maintainer@bidderA.com", 778 }, 779 Capabilities: &CapabilitiesInfo{}, 780 }, 781 }, 782 []error{ 783 errors.New("at least one of capabilities.site or capabilities.app must exist for adapter: bidderA"), 784 }, 785 }, 786 { 787 "One bidder incorrect capabilities for app", 788 BidderInfos{ 789 "bidderA": BidderInfo{ 790 Endpoint: "http://bidderA.com/openrtb2", 791 Maintainer: &MaintainerInfo{ 792 Email: "maintainer@bidderA.com", 793 }, 794 Capabilities: &CapabilitiesInfo{ 795 App: &PlatformInfo{ 796 MediaTypes: []openrtb_ext.BidType{ 797 "incorrect", 798 }, 799 }, 800 }, 801 }, 802 }, 803 []error{ 804 errors.New("capabilities.app failed validation: unrecognized media type at index 0: incorrect for adapter: bidderA"), 805 }, 806 }, 807 { 808 "One bidder nil capabilities", 809 BidderInfos{ 810 "bidderA": BidderInfo{ 811 Endpoint: "http://bidderA.com/openrtb2", 812 Maintainer: &MaintainerInfo{ 813 Email: "maintainer@bidderA.com", 814 }, 815 Capabilities: nil, 816 }, 817 }, 818 []error{ 819 errors.New("missing required field: capabilities for adapter: bidderA"), 820 }, 821 }, 822 { 823 "One bidder invalid syncer", 824 BidderInfos{ 825 "bidderA": BidderInfo{ 826 Endpoint: "http://bidderA.com/openrtb2", 827 Maintainer: &MaintainerInfo{ 828 Email: "maintainer@bidderA.com", 829 }, 830 Capabilities: &CapabilitiesInfo{ 831 Site: &PlatformInfo{ 832 MediaTypes: []openrtb_ext.BidType{ 833 openrtb_ext.BidTypeVideo, 834 }, 835 }, 836 }, 837 Syncer: &Syncer{ 838 Supports: []string{"incorrect"}, 839 }, 840 }, 841 }, 842 []error{ 843 errors.New("syncer could not be created, invalid supported endpoint: incorrect"), 844 }, 845 }, 846 { 847 "Two bidders, one with incorrect url", 848 BidderInfos{ 849 "bidderA": BidderInfo{ 850 Endpoint: "incorrect", 851 Maintainer: &MaintainerInfo{ 852 Email: "maintainer@bidderA.com", 853 }, 854 Capabilities: &CapabilitiesInfo{ 855 App: &PlatformInfo{ 856 MediaTypes: []openrtb_ext.BidType{ 857 openrtb_ext.BidTypeVideo, 858 }, 859 }, 860 }, 861 }, 862 "bidderB": BidderInfo{ 863 Endpoint: "http://bidderB.com/openrtb2", 864 Maintainer: &MaintainerInfo{ 865 Email: "maintainer@bidderB.com", 866 }, 867 Capabilities: &CapabilitiesInfo{ 868 App: &PlatformInfo{ 869 MediaTypes: []openrtb_ext.BidType{ 870 openrtb_ext.BidTypeVideo, 871 }, 872 }, 873 }, 874 }, 875 }, 876 []error{ 877 errors.New("The endpoint: incorrect for bidderA is not a valid URL"), 878 }, 879 }, 880 { 881 "Two bidders, both with incorrect url", 882 BidderInfos{ 883 "bidderA": BidderInfo{ 884 Endpoint: "incorrect", 885 Maintainer: &MaintainerInfo{ 886 Email: "maintainer@bidderA.com", 887 }, 888 Capabilities: &CapabilitiesInfo{ 889 App: &PlatformInfo{ 890 MediaTypes: []openrtb_ext.BidType{ 891 openrtb_ext.BidTypeVideo, 892 }, 893 }, 894 }, 895 }, 896 "bidderB": BidderInfo{ 897 Endpoint: "incorrect", 898 Maintainer: &MaintainerInfo{ 899 Email: "maintainer@bidderB.com", 900 }, 901 Capabilities: &CapabilitiesInfo{ 902 App: &PlatformInfo{ 903 MediaTypes: []openrtb_ext.BidType{ 904 openrtb_ext.BidTypeVideo, 905 }, 906 }, 907 }, 908 }, 909 }, 910 []error{ 911 errors.New("The endpoint: incorrect for bidderA is not a valid URL"), 912 errors.New("The endpoint: incorrect for bidderB is not a valid URL"), 913 }, 914 }, 915 { 916 "Invalid alias Site capabilities", 917 BidderInfos{ 918 "bidderA": BidderInfo{ 919 Endpoint: "http://bidderA.com/openrtb2", 920 Maintainer: &MaintainerInfo{ 921 Email: "maintainer@bidderA.com", 922 }, 923 Capabilities: &CapabilitiesInfo{ 924 Site: &PlatformInfo{ 925 MediaTypes: []openrtb_ext.BidType{ 926 openrtb_ext.BidTypeVideo, 927 }, 928 }, 929 }, 930 }, 931 "bidderB": BidderInfo{ 932 Endpoint: "http://bidderA.com/openrtb2", 933 Maintainer: &MaintainerInfo{ 934 Email: "maintainer@bidderA.com", 935 }, 936 Capabilities: &CapabilitiesInfo{ 937 App: &PlatformInfo{ 938 MediaTypes: []openrtb_ext.BidType{ 939 openrtb_ext.BidTypeVideo, 940 }, 941 }, 942 }, 943 AliasOf: "bidderA", 944 }, 945 }, 946 []error{ 947 errors.New("capabilities for alias: bidderB should be a subset of capabilities for parent bidder: bidderA"), 948 }, 949 }, 950 { 951 "Invalid alias App capabilities", 952 BidderInfos{ 953 "bidderA": BidderInfo{ 954 Endpoint: "http://bidderA.com/openrtb2", 955 Maintainer: &MaintainerInfo{ 956 Email: "maintainer@bidderA.com", 957 }, 958 Capabilities: &CapabilitiesInfo{ 959 App: &PlatformInfo{ 960 MediaTypes: []openrtb_ext.BidType{ 961 openrtb_ext.BidTypeVideo, 962 }, 963 }, 964 }, 965 }, 966 "bidderB": BidderInfo{ 967 Endpoint: "http://bidderA.com/openrtb2", 968 Maintainer: &MaintainerInfo{ 969 Email: "maintainer@bidderA.com", 970 }, 971 Capabilities: &CapabilitiesInfo{ 972 Site: &PlatformInfo{ 973 MediaTypes: []openrtb_ext.BidType{ 974 openrtb_ext.BidTypeVideo, 975 }, 976 }, 977 }, 978 AliasOf: "bidderA", 979 }, 980 }, 981 []error{ 982 errors.New("capabilities for alias: bidderB should be a subset of capabilities for parent bidder: bidderA"), 983 }, 984 }, 985 { 986 "Invalid alias capabilities", 987 BidderInfos{ 988 "bidderA": BidderInfo{ 989 Endpoint: "http://bidderA.com/openrtb2", 990 Maintainer: &MaintainerInfo{ 991 Email: "maintainer@bidderA.com", 992 }, 993 Capabilities: &CapabilitiesInfo{}, 994 }, 995 "bidderB": BidderInfo{ 996 Endpoint: "http://bidderA.com/openrtb2", 997 Maintainer: &MaintainerInfo{ 998 Email: "maintainer@bidderA.com", 999 }, 1000 Capabilities: &CapabilitiesInfo{ 1001 App: &PlatformInfo{ 1002 MediaTypes: []openrtb_ext.BidType{ 1003 openrtb_ext.BidTypeVideo, 1004 }, 1005 }, 1006 }, 1007 AliasOf: "bidderA", 1008 }, 1009 }, 1010 []error{ 1011 errors.New("at least one of capabilities.site or capabilities.app must exist for adapter: bidderA"), 1012 errors.New("capabilities for alias: bidderB should be a subset of capabilities for parent bidder: bidderA"), 1013 }, 1014 }, 1015 { 1016 "Invalid alias MediaTypes for site", 1017 BidderInfos{ 1018 "bidderA": BidderInfo{ 1019 Endpoint: "http://bidderA.com/openrtb2", 1020 Maintainer: &MaintainerInfo{ 1021 Email: "maintainer@bidderA.com", 1022 }, 1023 Capabilities: &CapabilitiesInfo{ 1024 Site: &PlatformInfo{ 1025 MediaTypes: []openrtb_ext.BidType{ 1026 openrtb_ext.BidTypeVideo, 1027 }, 1028 }, 1029 }, 1030 }, 1031 "bidderB": BidderInfo{ 1032 Endpoint: "http://bidderA.com/openrtb2", 1033 Maintainer: &MaintainerInfo{ 1034 Email: "maintainer@bidderA.com", 1035 }, 1036 Capabilities: &CapabilitiesInfo{ 1037 Site: &PlatformInfo{ 1038 MediaTypes: []openrtb_ext.BidType{ 1039 openrtb_ext.BidTypeBanner, 1040 openrtb_ext.BidTypeNative, 1041 }, 1042 }, 1043 }, 1044 AliasOf: "bidderA", 1045 }, 1046 }, 1047 []error{ 1048 errors.New("mediaTypes for alias: bidderB should be a subset of MediaTypes for parent bidder: bidderA"), 1049 }, 1050 }, 1051 { 1052 "Invalid alias MediaTypes for app", 1053 BidderInfos{ 1054 "bidderA": BidderInfo{ 1055 Endpoint: "http://bidderA.com/openrtb2", 1056 Maintainer: &MaintainerInfo{ 1057 Email: "maintainer@bidderA.com", 1058 }, 1059 Capabilities: &CapabilitiesInfo{ 1060 App: &PlatformInfo{ 1061 MediaTypes: []openrtb_ext.BidType{ 1062 openrtb_ext.BidTypeVideo, 1063 }, 1064 }, 1065 }, 1066 }, 1067 "bidderB": BidderInfo{ 1068 Endpoint: "http://bidderA.com/openrtb2", 1069 Maintainer: &MaintainerInfo{ 1070 Email: "maintainer@bidderA.com", 1071 }, 1072 Capabilities: &CapabilitiesInfo{ 1073 App: &PlatformInfo{ 1074 MediaTypes: []openrtb_ext.BidType{ 1075 openrtb_ext.BidTypeBanner, 1076 openrtb_ext.BidTypeNative, 1077 }, 1078 }, 1079 }, 1080 AliasOf: "bidderA", 1081 }, 1082 }, 1083 []error{ 1084 errors.New("mediaTypes for alias: bidderB should be a subset of MediaTypes for parent bidder: bidderA"), 1085 }, 1086 }, 1087 { 1088 "Invalid parent bidder capabilities", 1089 BidderInfos{ 1090 "bidderA": BidderInfo{ 1091 Endpoint: "http://bidderA.com/openrtb2", 1092 Maintainer: &MaintainerInfo{ 1093 Email: "maintainer@bidderA.com", 1094 }, 1095 }, 1096 "bidderB": BidderInfo{ 1097 Endpoint: "http://bidderA.com/openrtb2", 1098 Maintainer: &MaintainerInfo{ 1099 Email: "maintainer@bidderA.com", 1100 }, 1101 Capabilities: &CapabilitiesInfo{ 1102 App: &PlatformInfo{ 1103 MediaTypes: []openrtb_ext.BidType{ 1104 openrtb_ext.BidTypeBanner, 1105 }, 1106 }, 1107 }, 1108 AliasOf: "bidderA", 1109 }, 1110 }, 1111 []error{ 1112 errors.New("missing required field: capabilities for adapter: bidderA"), 1113 errors.New("capabilities for alias: bidderB should be a subset of capabilities for parent bidder: bidderA"), 1114 }, 1115 }, 1116 { 1117 "Invalid site alias capabilities with both site and app", 1118 BidderInfos{ 1119 "bidderA": BidderInfo{ 1120 Endpoint: "http://bidderA.com/openrtb2", 1121 Maintainer: &MaintainerInfo{ 1122 Email: "maintainer@bidderA.com", 1123 }, 1124 Capabilities: &CapabilitiesInfo{ 1125 App: &PlatformInfo{ 1126 MediaTypes: []openrtb_ext.BidType{ 1127 openrtb_ext.BidTypeBanner, 1128 openrtb_ext.BidTypeNative, 1129 }, 1130 }, 1131 Site: &PlatformInfo{ 1132 MediaTypes: []openrtb_ext.BidType{ 1133 openrtb_ext.BidTypeNative, 1134 }, 1135 }, 1136 }, 1137 }, 1138 "bidderB": BidderInfo{ 1139 Endpoint: "http://bidderA.com/openrtb2", 1140 Maintainer: &MaintainerInfo{ 1141 Email: "maintainer@bidderA.com", 1142 }, 1143 Capabilities: &CapabilitiesInfo{ 1144 App: &PlatformInfo{ 1145 MediaTypes: []openrtb_ext.BidType{ 1146 openrtb_ext.BidTypeBanner, 1147 openrtb_ext.BidTypeNative, 1148 }, 1149 }, 1150 Site: &PlatformInfo{ 1151 MediaTypes: []openrtb_ext.BidType{ 1152 openrtb_ext.BidTypeBanner, 1153 openrtb_ext.BidTypeNative, 1154 }, 1155 }, 1156 }, 1157 AliasOf: "bidderA", 1158 }, 1159 }, 1160 []error{ 1161 errors.New("mediaTypes for alias: bidderB should be a subset of MediaTypes for parent bidder: bidderA"), 1162 }, 1163 }, 1164 { 1165 "Invalid app alias capabilities with both site and app", 1166 BidderInfos{ 1167 "bidderA": BidderInfo{ 1168 Endpoint: "http://bidderA.com/openrtb2", 1169 Maintainer: &MaintainerInfo{ 1170 Email: "maintainer@bidderA.com", 1171 }, 1172 Capabilities: &CapabilitiesInfo{ 1173 App: &PlatformInfo{ 1174 MediaTypes: []openrtb_ext.BidType{ 1175 openrtb_ext.BidTypeBanner, 1176 openrtb_ext.BidTypeNative, 1177 }, 1178 }, 1179 Site: &PlatformInfo{ 1180 MediaTypes: []openrtb_ext.BidType{ 1181 openrtb_ext.BidTypeNative, 1182 }, 1183 }, 1184 }, 1185 }, 1186 "bidderB": BidderInfo{ 1187 Endpoint: "http://bidderA.com/openrtb2", 1188 Maintainer: &MaintainerInfo{ 1189 Email: "maintainer@bidderA.com", 1190 }, 1191 Capabilities: &CapabilitiesInfo{ 1192 App: &PlatformInfo{ 1193 MediaTypes: []openrtb_ext.BidType{ 1194 openrtb_ext.BidTypeBanner, 1195 openrtb_ext.BidTypeNative, 1196 }, 1197 }, 1198 Site: &PlatformInfo{ 1199 MediaTypes: []openrtb_ext.BidType{ 1200 openrtb_ext.BidTypeBanner, 1201 openrtb_ext.BidTypeNative, 1202 }, 1203 }, 1204 }, 1205 AliasOf: "bidderA", 1206 }, 1207 }, 1208 []error{ 1209 errors.New("mediaTypes for alias: bidderB should be a subset of MediaTypes for parent bidder: bidderA"), 1210 }, 1211 }, 1212 { 1213 "Invalid parent bidder for alias", 1214 BidderInfos{ 1215 "bidderB": BidderInfo{ 1216 Endpoint: "http://bidderA.com/openrtb2", 1217 Maintainer: &MaintainerInfo{ 1218 Email: "maintainer@bidderA.com", 1219 }, 1220 Capabilities: &CapabilitiesInfo{ 1221 App: &PlatformInfo{ 1222 MediaTypes: []openrtb_ext.BidType{ 1223 openrtb_ext.BidTypeBanner, 1224 openrtb_ext.BidTypeNative, 1225 }, 1226 }, 1227 Site: &PlatformInfo{ 1228 MediaTypes: []openrtb_ext.BidType{ 1229 openrtb_ext.BidTypeBanner, 1230 openrtb_ext.BidTypeNative, 1231 }, 1232 }, 1233 }, 1234 AliasOf: "bidderC", 1235 }, 1236 }, 1237 []error{ 1238 errors.New("parent bidder: bidderC not found for an alias: bidderB"), 1239 }, 1240 }, 1241 } 1242 1243 for _, test := range testCases { 1244 errs := test.bidderInfos.validate(make([]error, 0)) 1245 assert.ElementsMatch(t, errs, test.expectErrors, "incorrect errors returned for test: %s", test.description) 1246 } 1247 } 1248 1249 func TestSyncerOverride(t *testing.T) { 1250 var ( 1251 trueValue = true 1252 falseValue = false 1253 ) 1254 1255 testCases := []struct { 1256 description string 1257 givenOriginal *Syncer 1258 givenOverride *Syncer 1259 expected *Syncer 1260 }{ 1261 { 1262 description: "Nil", 1263 givenOriginal: nil, 1264 givenOverride: nil, 1265 expected: nil, 1266 }, 1267 { 1268 description: "Original Nil", 1269 givenOriginal: nil, 1270 givenOverride: &Syncer{Key: "anyKey"}, 1271 expected: &Syncer{Key: "anyKey"}, 1272 }, 1273 { 1274 description: "Original Empty", 1275 givenOriginal: &Syncer{}, 1276 givenOverride: &Syncer{Key: "anyKey"}, 1277 expected: &Syncer{Key: "anyKey"}, 1278 }, 1279 { 1280 description: "Override Nil", 1281 givenOriginal: &Syncer{Key: "anyKey"}, 1282 givenOverride: nil, 1283 expected: &Syncer{Key: "anyKey"}, 1284 }, 1285 { 1286 description: "Override Empty", 1287 givenOriginal: &Syncer{Key: "anyKey"}, 1288 givenOverride: &Syncer{}, 1289 expected: &Syncer{Key: "anyKey"}, 1290 }, 1291 { 1292 description: "Override Key", 1293 givenOriginal: &Syncer{Key: "original"}, 1294 givenOverride: &Syncer{Key: "override"}, 1295 expected: &Syncer{Key: "override"}, 1296 }, 1297 { 1298 description: "Override IFrame", 1299 givenOriginal: &Syncer{IFrame: &SyncerEndpoint{URL: "original"}}, 1300 givenOverride: &Syncer{IFrame: &SyncerEndpoint{URL: "override"}}, 1301 expected: &Syncer{IFrame: &SyncerEndpoint{URL: "override"}}, 1302 }, 1303 { 1304 description: "Override Redirect", 1305 givenOriginal: &Syncer{Redirect: &SyncerEndpoint{URL: "original"}}, 1306 givenOverride: &Syncer{Redirect: &SyncerEndpoint{URL: "override"}}, 1307 expected: &Syncer{Redirect: &SyncerEndpoint{URL: "override"}}, 1308 }, 1309 { 1310 description: "Override ExternalURL", 1311 givenOriginal: &Syncer{ExternalURL: "original"}, 1312 givenOverride: &Syncer{ExternalURL: "override"}, 1313 expected: &Syncer{ExternalURL: "override"}, 1314 }, 1315 { 1316 description: "Override SupportCORS", 1317 givenOriginal: &Syncer{SupportCORS: &trueValue}, 1318 givenOverride: &Syncer{SupportCORS: &falseValue}, 1319 expected: &Syncer{SupportCORS: &falseValue}, 1320 }, 1321 { 1322 description: "Override Partial - Other Fields Untouched", 1323 givenOriginal: &Syncer{Key: "originalKey", ExternalURL: "originalExternalURL"}, 1324 givenOverride: &Syncer{ExternalURL: "overrideExternalURL"}, 1325 expected: &Syncer{Key: "originalKey", ExternalURL: "overrideExternalURL"}, 1326 }, 1327 } 1328 1329 for _, test := range testCases { 1330 result := test.givenOverride.Override(test.givenOriginal) 1331 assert.Equal(t, test.expected, result, test.description) 1332 } 1333 } 1334 1335 func TestSyncerEndpointOverride(t *testing.T) { 1336 testCases := []struct { 1337 description string 1338 givenOriginal *SyncerEndpoint 1339 givenOverride *SyncerEndpoint 1340 expected *SyncerEndpoint 1341 }{ 1342 { 1343 description: "Nil", 1344 givenOriginal: nil, 1345 givenOverride: nil, 1346 expected: nil, 1347 }, 1348 { 1349 description: "Original Nil", 1350 givenOriginal: nil, 1351 givenOverride: &SyncerEndpoint{URL: "anyURL"}, 1352 expected: &SyncerEndpoint{URL: "anyURL"}, 1353 }, 1354 { 1355 description: "Original Empty", 1356 givenOriginal: &SyncerEndpoint{}, 1357 givenOverride: &SyncerEndpoint{URL: "anyURL"}, 1358 expected: &SyncerEndpoint{URL: "anyURL"}, 1359 }, 1360 { 1361 description: "Override Nil", 1362 givenOriginal: &SyncerEndpoint{URL: "anyURL"}, 1363 givenOverride: nil, 1364 expected: &SyncerEndpoint{URL: "anyURL"}, 1365 }, 1366 { 1367 description: "Override Empty", 1368 givenOriginal: &SyncerEndpoint{URL: "anyURL"}, 1369 givenOverride: &SyncerEndpoint{}, 1370 expected: &SyncerEndpoint{URL: "anyURL"}, 1371 }, 1372 { 1373 description: "Override URL", 1374 givenOriginal: &SyncerEndpoint{URL: "original"}, 1375 givenOverride: &SyncerEndpoint{URL: "override"}, 1376 expected: &SyncerEndpoint{URL: "override"}, 1377 }, 1378 { 1379 description: "Override RedirectURL", 1380 givenOriginal: &SyncerEndpoint{RedirectURL: "original"}, 1381 givenOverride: &SyncerEndpoint{RedirectURL: "override"}, 1382 expected: &SyncerEndpoint{RedirectURL: "override"}, 1383 }, 1384 { 1385 description: "Override ExternalURL", 1386 givenOriginal: &SyncerEndpoint{ExternalURL: "original"}, 1387 givenOverride: &SyncerEndpoint{ExternalURL: "override"}, 1388 expected: &SyncerEndpoint{ExternalURL: "override"}, 1389 }, 1390 { 1391 description: "Override UserMacro", 1392 givenOriginal: &SyncerEndpoint{UserMacro: "original"}, 1393 givenOverride: &SyncerEndpoint{UserMacro: "override"}, 1394 expected: &SyncerEndpoint{UserMacro: "override"}, 1395 }, 1396 { 1397 description: "Override", 1398 givenOriginal: &SyncerEndpoint{URL: "originalURL", RedirectURL: "originalRedirectURL", ExternalURL: "originalExternalURL", UserMacro: "originalUserMacro"}, 1399 givenOverride: &SyncerEndpoint{URL: "overideURL", RedirectURL: "overideRedirectURL", ExternalURL: "overideExternalURL", UserMacro: "overideUserMacro"}, 1400 expected: &SyncerEndpoint{URL: "overideURL", RedirectURL: "overideRedirectURL", ExternalURL: "overideExternalURL", UserMacro: "overideUserMacro"}, 1401 }, 1402 } 1403 1404 for _, test := range testCases { 1405 result := test.givenOverride.Override(test.givenOriginal) 1406 assert.Equal(t, test.expected, result, test.description) 1407 } 1408 } 1409 1410 func TestApplyBidderInfoConfigSyncerOverrides(t *testing.T) { 1411 var testCases = []struct { 1412 description string 1413 givenFsBidderInfos BidderInfos 1414 givenConfigBidderInfos BidderInfos 1415 expectedError string 1416 expectedBidderInfos BidderInfos 1417 }{ 1418 { 1419 description: "Syncer Override", 1420 givenFsBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "original"}}}, 1421 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1422 expectedBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1423 }, 1424 { 1425 description: "UserSyncURL Override IFrame", 1426 givenFsBidderInfos: BidderInfos{"a": {Syncer: &Syncer{IFrame: &SyncerEndpoint{URL: "original"}}}}, 1427 givenConfigBidderInfos: BidderInfos{"a": {UserSyncURL: "override"}}, 1428 expectedBidderInfos: BidderInfos{"a": {UserSyncURL: "override", Syncer: &Syncer{IFrame: &SyncerEndpoint{URL: "override"}}}}, 1429 }, 1430 { 1431 description: "UserSyncURL Supports IFrame", 1432 givenFsBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Supports: []string{"iframe"}}}}, 1433 givenConfigBidderInfos: BidderInfos{"a": {UserSyncURL: "override"}}, 1434 expectedBidderInfos: BidderInfos{"a": {UserSyncURL: "override", Syncer: &Syncer{Supports: []string{"iframe"}, IFrame: &SyncerEndpoint{URL: "override"}}}}, 1435 }, 1436 { 1437 description: "UserSyncURL Override Redirect", 1438 givenFsBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Supports: []string{"redirect"}}}}, 1439 givenConfigBidderInfos: BidderInfos{"a": {UserSyncURL: "override"}}, 1440 expectedBidderInfos: BidderInfos{"a": {UserSyncURL: "override", Syncer: &Syncer{Supports: []string{"redirect"}, Redirect: &SyncerEndpoint{URL: "override"}}}}, 1441 }, 1442 { 1443 description: "UserSyncURL Supports Redirect", 1444 givenFsBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Redirect: &SyncerEndpoint{URL: "original"}}}}, 1445 givenConfigBidderInfos: BidderInfos{"a": {UserSyncURL: "override"}}, 1446 expectedBidderInfos: BidderInfos{"a": {UserSyncURL: "override", Syncer: &Syncer{Redirect: &SyncerEndpoint{URL: "override"}}}}, 1447 }, 1448 { 1449 description: "UserSyncURL Override Syncer Not Defined", 1450 givenFsBidderInfos: BidderInfos{"a": {}}, 1451 givenConfigBidderInfos: BidderInfos{"a": {UserSyncURL: "override"}}, 1452 expectedError: "adapters.a.usersync_url cannot be applied, bidder does not define a user sync", 1453 }, 1454 { 1455 description: "UserSyncURL Override Syncer Endpoints Not Defined", 1456 givenFsBidderInfos: BidderInfos{"a": {Syncer: &Syncer{}}}, 1457 givenConfigBidderInfos: BidderInfos{"a": {UserSyncURL: "override"}}, 1458 expectedError: "adapters.a.usersync_url cannot be applied, bidder does not define user sync endpoints and does not define supported endpoints", 1459 }, 1460 { 1461 description: "UserSyncURL Override Ambiguous", 1462 givenFsBidderInfos: BidderInfos{"a": {Syncer: &Syncer{IFrame: &SyncerEndpoint{URL: "originalIFrame"}, Redirect: &SyncerEndpoint{URL: "originalRedirect"}}}}, 1463 givenConfigBidderInfos: BidderInfos{"a": {UserSyncURL: "override"}}, 1464 expectedError: "adapters.a.usersync_url cannot be applied, bidder defines multiple user sync endpoints or supports multiple endpoints", 1465 }, 1466 { 1467 description: "UserSyncURL Supports Ambiguous", 1468 givenFsBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Supports: []string{"iframe", "redirect"}}}}, 1469 givenConfigBidderInfos: BidderInfos{"a": {UserSyncURL: "override"}}, 1470 expectedError: "adapters.a.usersync_url cannot be applied, bidder defines multiple user sync endpoints or supports multiple endpoints", 1471 }, 1472 } 1473 1474 for _, test := range testCases { 1475 bidderInfos, resultErr := applyBidderInfoConfigOverrides(test.givenConfigBidderInfos, test.givenFsBidderInfos, mockNormalizeBidderName) 1476 if test.expectedError == "" { 1477 assert.NoError(t, resultErr, test.description+":err") 1478 assert.Equal(t, test.expectedBidderInfos, bidderInfos, test.description+":result") 1479 } else { 1480 assert.EqualError(t, resultErr, test.expectedError, test.description+":err") 1481 } 1482 } 1483 } 1484 1485 func TestApplyBidderInfoConfigOverrides(t *testing.T) { 1486 var testCases = []struct { 1487 description string 1488 givenFsBidderInfos BidderInfos 1489 givenConfigBidderInfos BidderInfos 1490 expectedError string 1491 expectedBidderInfos BidderInfos 1492 }{ 1493 { 1494 description: "Don't override endpoint", 1495 givenFsBidderInfos: BidderInfos{"a": {Endpoint: "original"}}, 1496 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1497 expectedBidderInfos: BidderInfos{"a": {Endpoint: "original", Syncer: &Syncer{Key: "override"}}}, 1498 }, 1499 { 1500 description: "Override endpoint", 1501 givenFsBidderInfos: BidderInfos{"a": {Endpoint: "original"}}, 1502 givenConfigBidderInfos: BidderInfos{"a": {Endpoint: "override", Syncer: &Syncer{Key: "override"}}}, 1503 expectedBidderInfos: BidderInfos{"a": {Endpoint: "override", Syncer: &Syncer{Key: "override"}}}, 1504 }, 1505 { 1506 description: "Don't override ExtraAdapterInfo", 1507 givenFsBidderInfos: BidderInfos{"a": {ExtraAdapterInfo: "original"}}, 1508 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1509 expectedBidderInfos: BidderInfos{"a": {ExtraAdapterInfo: "original", Syncer: &Syncer{Key: "override"}}}, 1510 }, 1511 { 1512 description: "Override ExtraAdapterInfo", 1513 givenFsBidderInfos: BidderInfos{"a": {ExtraAdapterInfo: "original"}}, 1514 givenConfigBidderInfos: BidderInfos{"a": {ExtraAdapterInfo: "override", Syncer: &Syncer{Key: "override"}}}, 1515 expectedBidderInfos: BidderInfos{"a": {ExtraAdapterInfo: "override", Syncer: &Syncer{Key: "override"}}}, 1516 }, 1517 { 1518 description: "Don't override Maintainer", 1519 givenFsBidderInfos: BidderInfos{"a": {Maintainer: &MaintainerInfo{Email: "original"}}}, 1520 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1521 expectedBidderInfos: BidderInfos{"a": {Maintainer: &MaintainerInfo{Email: "original"}, Syncer: &Syncer{Key: "override"}}}, 1522 }, 1523 { 1524 description: "Override maintainer", 1525 givenFsBidderInfos: BidderInfos{"a": {Maintainer: &MaintainerInfo{Email: "original"}}}, 1526 givenConfigBidderInfos: BidderInfos{"a": {Maintainer: &MaintainerInfo{Email: "override"}, Syncer: &Syncer{Key: "override"}}}, 1527 expectedBidderInfos: BidderInfos{"a": {Maintainer: &MaintainerInfo{Email: "override"}, Syncer: &Syncer{Key: "override"}}}, 1528 }, 1529 { 1530 description: "Don't override Capabilities", 1531 givenFsBidderInfos: BidderInfos{"a": { 1532 Capabilities: &CapabilitiesInfo{App: &PlatformInfo{MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeVideo}}}, 1533 }}, 1534 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1535 expectedBidderInfos: BidderInfos{"a": { 1536 Syncer: &Syncer{Key: "override"}, 1537 Capabilities: &CapabilitiesInfo{App: &PlatformInfo{MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeVideo}}}, 1538 }}, 1539 }, 1540 { 1541 description: "Override Capabilities", 1542 givenFsBidderInfos: BidderInfos{"a": { 1543 Capabilities: &CapabilitiesInfo{App: &PlatformInfo{MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeVideo}}}, 1544 }}, 1545 givenConfigBidderInfos: BidderInfos{"a": { 1546 Syncer: &Syncer{Key: "override"}, 1547 Capabilities: &CapabilitiesInfo{App: &PlatformInfo{MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner}}}, 1548 }}, 1549 expectedBidderInfos: BidderInfos{"a": { 1550 Syncer: &Syncer{Key: "override"}, 1551 Capabilities: &CapabilitiesInfo{App: &PlatformInfo{MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner}}}, 1552 }}, 1553 }, 1554 { 1555 description: "Don't override Debug", 1556 givenFsBidderInfos: BidderInfos{"a": {Debug: &DebugInfo{Allow: true}}}, 1557 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1558 expectedBidderInfos: BidderInfos{"a": {Debug: &DebugInfo{Allow: true}, Syncer: &Syncer{Key: "override"}}}, 1559 }, 1560 { 1561 description: "Override Debug", 1562 givenFsBidderInfos: BidderInfos{"a": {Debug: &DebugInfo{Allow: true}}}, 1563 givenConfigBidderInfos: BidderInfos{"a": {Debug: &DebugInfo{Allow: false}, Syncer: &Syncer{Key: "override"}}}, 1564 expectedBidderInfos: BidderInfos{"a": {Debug: &DebugInfo{Allow: false}, Syncer: &Syncer{Key: "override"}}}, 1565 }, 1566 { 1567 description: "Don't override GVLVendorID", 1568 givenFsBidderInfos: BidderInfos{"a": {GVLVendorID: 5}}, 1569 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1570 expectedBidderInfos: BidderInfos{"a": {GVLVendorID: 5, Syncer: &Syncer{Key: "override"}}}, 1571 }, 1572 { 1573 description: "Override GVLVendorID", 1574 givenFsBidderInfos: BidderInfos{"a": {}}, 1575 givenConfigBidderInfos: BidderInfos{"a": {GVLVendorID: 5, Syncer: &Syncer{Key: "override"}}}, 1576 expectedBidderInfos: BidderInfos{"a": {GVLVendorID: 5, Syncer: &Syncer{Key: "override"}}}, 1577 }, 1578 { 1579 description: "Don't override XAPI", 1580 givenFsBidderInfos: BidderInfos{"a": { 1581 XAPI: AdapterXAPI{Username: "username1", Password: "password2", Tracker: "tracker3"}, 1582 }}, 1583 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1584 expectedBidderInfos: BidderInfos{"a": { 1585 XAPI: AdapterXAPI{Username: "username1", Password: "password2", Tracker: "tracker3"}, 1586 Syncer: &Syncer{Key: "override"}}}, 1587 }, 1588 { 1589 description: "Override XAPI", 1590 givenFsBidderInfos: BidderInfos{"a": { 1591 XAPI: AdapterXAPI{Username: "username", Password: "password", Tracker: "tracker"}}}, 1592 givenConfigBidderInfos: BidderInfos{"a": { 1593 XAPI: AdapterXAPI{Username: "username1", Password: "password2", Tracker: "tracker3"}, 1594 Syncer: &Syncer{Key: "override"}}}, 1595 expectedBidderInfos: BidderInfos{"a": { 1596 XAPI: AdapterXAPI{Username: "username1", Password: "password2", Tracker: "tracker3"}, 1597 Syncer: &Syncer{Key: "override"}}}, 1598 }, 1599 { 1600 description: "Don't override PlatformID", 1601 givenFsBidderInfos: BidderInfos{"a": {PlatformID: "PlatformID"}}, 1602 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1603 expectedBidderInfos: BidderInfos{"a": {PlatformID: "PlatformID", Syncer: &Syncer{Key: "override"}}}, 1604 }, 1605 { 1606 description: "Override PlatformID", 1607 givenFsBidderInfos: BidderInfos{"a": {PlatformID: "PlatformID1"}}, 1608 givenConfigBidderInfos: BidderInfos{"a": {PlatformID: "PlatformID2", Syncer: &Syncer{Key: "override"}}}, 1609 expectedBidderInfos: BidderInfos{"a": {PlatformID: "PlatformID2", Syncer: &Syncer{Key: "override"}}}, 1610 }, 1611 { 1612 description: "Don't override AppSecret", 1613 givenFsBidderInfos: BidderInfos{"a": {AppSecret: "AppSecret"}}, 1614 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1615 expectedBidderInfos: BidderInfos{"a": {AppSecret: "AppSecret", Syncer: &Syncer{Key: "override"}}}, 1616 }, 1617 { 1618 description: "Override AppSecret", 1619 givenFsBidderInfos: BidderInfos{"a": {AppSecret: "AppSecret1"}}, 1620 givenConfigBidderInfos: BidderInfos{"a": {AppSecret: "AppSecret2", Syncer: &Syncer{Key: "override"}}}, 1621 expectedBidderInfos: BidderInfos{"a": {AppSecret: "AppSecret2", Syncer: &Syncer{Key: "override"}}}, 1622 }, 1623 { 1624 description: "Don't override EndpointCompression", 1625 givenFsBidderInfos: BidderInfos{"a": {EndpointCompression: "GZIP"}}, 1626 givenConfigBidderInfos: BidderInfos{"a": {Syncer: &Syncer{Key: "override"}}}, 1627 expectedBidderInfos: BidderInfos{"a": {EndpointCompression: "GZIP", Syncer: &Syncer{Key: "override"}}}, 1628 }, 1629 { 1630 description: "Override EndpointCompression", 1631 givenFsBidderInfos: BidderInfos{"a": {EndpointCompression: "GZIP"}}, 1632 givenConfigBidderInfos: BidderInfos{"a": {EndpointCompression: "LZ77", Syncer: &Syncer{Key: "override"}}}, 1633 expectedBidderInfos: BidderInfos{"a": {EndpointCompression: "LZ77", Syncer: &Syncer{Key: "override"}}}, 1634 }, 1635 } 1636 for _, test := range testCases { 1637 bidderInfos, resultErr := applyBidderInfoConfigOverrides(test.givenConfigBidderInfos, test.givenFsBidderInfos, mockNormalizeBidderName) 1638 assert.NoError(t, resultErr, test.description+":err") 1639 assert.Equal(t, test.expectedBidderInfos, bidderInfos, test.description+":result") 1640 } 1641 } 1642 1643 func TestApplyBidderInfoConfigOverridesInvalid(t *testing.T) { 1644 var testCases = []struct { 1645 description string 1646 givenFsBidderInfos BidderInfos 1647 givenConfigBidderInfos BidderInfos 1648 expectedError string 1649 expectedBidderInfos BidderInfos 1650 }{ 1651 { 1652 description: "Bidder doesn't exists in bidder list", 1653 givenConfigBidderInfos: BidderInfos{"unknown": {Syncer: &Syncer{Key: "override"}}}, 1654 expectedError: "error setting configuration for bidder unknown: unknown bidder", 1655 }, 1656 { 1657 description: "Bidder doesn't exists in file system", 1658 givenFsBidderInfos: BidderInfos{"unknown": {Endpoint: "original"}}, 1659 givenConfigBidderInfos: BidderInfos{"bidderA": {Syncer: &Syncer{Key: "override"}}}, 1660 expectedError: "error finding configuration for bidder bidderA: unknown bidder", 1661 }, 1662 } 1663 for _, test := range testCases { 1664 _, err := applyBidderInfoConfigOverrides(test.givenConfigBidderInfos, test.givenFsBidderInfos, mockNormalizeBidderName) 1665 assert.ErrorContains(t, err, test.expectedError, test.description+":err") 1666 } 1667 } 1668 1669 func TestReadFullYamlBidderConfig(t *testing.T) { 1670 bidder := "bidderA" 1671 bidderInf := BidderInfo{} 1672 err := yaml.Unmarshal([]byte(fullBidderYAMLConfig), &bidderInf) 1673 actualBidderInfo, err := applyBidderInfoConfigOverrides(BidderInfos{bidder: bidderInf}, BidderInfos{bidder: {Syncer: &Syncer{Supports: []string{"iframe"}}}}, mockNormalizeBidderName) 1674 1675 assert.NoError(t, err, "Error wasn't expected") 1676 1677 expectedBidderInfo := BidderInfos{ 1678 bidder: { 1679 Maintainer: &MaintainerInfo{ 1680 Email: "some-email@domain.com", 1681 }, 1682 GVLVendorID: 42, 1683 Capabilities: &CapabilitiesInfo{ 1684 App: &PlatformInfo{ 1685 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative}, 1686 }, 1687 Site: &PlatformInfo{ 1688 MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative}, 1689 }, 1690 }, 1691 ModifyingVastXmlAllowed: true, 1692 Debug: &DebugInfo{ 1693 Allow: true, 1694 }, 1695 Experiment: BidderInfoExperiment{ 1696 AdsCert: BidderAdsCert{ 1697 Enabled: true, 1698 }, 1699 }, 1700 EndpointCompression: "GZIP", 1701 OpenRTB: &OpenRTBInfo{ 1702 GPPSupported: true, 1703 Version: "2.6", 1704 }, 1705 Disabled: false, 1706 ExtraAdapterInfo: "extra-info", 1707 AppSecret: "app-secret", 1708 PlatformID: "123", 1709 UserSyncURL: "user-url", 1710 Syncer: &Syncer{ 1711 Key: "foo", 1712 IFrame: &SyncerEndpoint{ 1713 URL: "user-url", 1714 RedirectURL: "https://redirect/setuid/iframe", 1715 ExternalURL: "https://iframe.host", 1716 UserMacro: "UID", 1717 }, 1718 Supports: []string{"iframe"}, 1719 }, 1720 XAPI: AdapterXAPI{ 1721 Username: "uname", 1722 Password: "pwd", 1723 Tracker: "tracker", 1724 }, 1725 Endpoint: "https://endpoint.com", 1726 }, 1727 } 1728 assert.Equalf(t, expectedBidderInfo, actualBidderInfo, "Bidder info objects aren't matching") 1729 }