github.com/prebid/prebid-server@v0.275.0/floors/rule_test.go (about) 1 package floors 2 3 import ( 4 "encoding/json" 5 "errors" 6 "testing" 7 8 "github.com/prebid/openrtb/v19/openrtb2" 9 "github.com/prebid/prebid-server/currency" 10 "github.com/prebid/prebid-server/openrtb_ext" 11 "github.com/stretchr/testify/assert" 12 ) 13 14 func TestPrepareRuleCombinations(t *testing.T) { 15 testCases := []struct { 16 name string 17 in []string 18 del string 19 exp []string 20 }{ 21 { 22 name: "Schema items, n = 1", 23 in: []string{"A"}, 24 del: "|", 25 exp: []string{ 26 "a", 27 "*", 28 }, 29 }, 30 { 31 name: "Schema items, n = 2", 32 in: []string{"A", "B"}, 33 del: "|", 34 exp: []string{ 35 "a|b", 36 "a|*", 37 "*|b", 38 "*|*", 39 }, 40 }, 41 { 42 name: "Schema items, n = 3", 43 in: []string{"A", "B", "C"}, 44 del: "|", 45 exp: []string{ 46 "a|b|c", 47 "a|b|*", 48 "a|*|c", 49 "*|b|c", 50 "a|*|*", 51 "*|b|*", 52 "*|*|c", 53 "*|*|*", 54 }, 55 }, 56 { 57 name: "Schema items, n = 4", 58 in: []string{"A", "B", "C", "D"}, 59 del: "|", 60 exp: []string{ 61 "a|b|c|d", 62 "a|b|c|*", 63 "a|b|*|d", 64 "a|*|c|d", 65 "*|b|c|d", 66 "a|b|*|*", 67 "a|*|c|*", 68 "a|*|*|d", 69 "*|b|c|*", 70 "*|b|*|d", 71 "*|*|c|d", 72 "a|*|*|*", 73 "*|b|*|*", 74 "*|*|c|*", 75 "*|*|*|d", 76 "*|*|*|*", 77 }, 78 }, 79 { 80 name: "Schema items, n = 1 with wildcards", 81 in: []string{"*"}, 82 del: "|", 83 exp: []string{ 84 "*", 85 }, 86 }, 87 { 88 name: "Schema items, n = 2 with wildcard at index = 0", 89 in: []string{"*", "B"}, 90 del: "|", 91 exp: []string{ 92 "*|b", 93 "*|*", 94 }, 95 }, 96 { 97 name: "Schema items, n = 2 with wildcards at index = 1", 98 in: []string{"A", "*"}, 99 del: "|", 100 exp: []string{ 101 "a|*", 102 "*|*", 103 }, 104 }, 105 106 { 107 name: "Schema items, n = 2 wildcards at index = 0,1", 108 in: []string{"*", "*"}, 109 del: "|", 110 exp: []string{ 111 "*|*", 112 }, 113 }, 114 115 { 116 name: "Schema items, n = 3 wildcard at index = 0", 117 in: []string{"*", "B", "C"}, 118 del: "|", 119 exp: []string{ 120 "*|b|c", 121 "*|b|*", 122 "*|*|c", 123 "*|*|*", 124 }, 125 }, 126 { 127 name: "Schema items, n = 3 wildcard at index = 1", 128 in: []string{"A", "*", "C"}, 129 del: "|", 130 exp: []string{ 131 "a|*|c", 132 "a|*|*", 133 "*|*|c", 134 "*|*|*", 135 }, 136 }, 137 { 138 name: "Schema items, n = 3 with wildcard at index = 2", 139 in: []string{"A", "B", "*"}, 140 del: "|", 141 exp: []string{ 142 "a|b|*", 143 "a|*|*", 144 "*|b|*", 145 "*|*|*", 146 }, 147 }, 148 { 149 name: "Schema items, n = 3 with wildcard at index = 0,2", 150 in: []string{"*", "B", "*"}, 151 del: "|", 152 exp: []string{ 153 "*|b|*", 154 "*|*|*", 155 }, 156 }, 157 { 158 name: "Schema items, n = 3 with wildcard at index = 0,1", 159 in: []string{"*", "*", "C"}, 160 del: "|", 161 exp: []string{ 162 "*|*|c", 163 "*|*|*", 164 }, 165 }, 166 { 167 name: "Schema items, n = 3 with wildcard at index = 1,2", 168 in: []string{"A", "*", "*"}, 169 del: "|", 170 exp: []string{ 171 "a|*|*", 172 "*|*|*", 173 }, 174 }, 175 } 176 for _, tc := range testCases { 177 t.Run(tc.name, func(t *testing.T) { 178 act := prepareRuleCombinations(tc.in, tc.del) 179 assert.Equal(t, tc.exp, act, tc.name) 180 }) 181 } 182 } 183 184 func TestUpdateImpExtWithFloorDetails(t *testing.T) { 185 testCases := []struct { 186 name string 187 matchedRule string 188 floorRuleVal float64 189 floorVal float64 190 imp *openrtb_ext.ImpWrapper 191 expected json.RawMessage 192 }{ 193 { 194 name: "Nil ImpExt", 195 matchedRule: "test|123|xyz", 196 floorRuleVal: 5.5, 197 floorVal: 5.5, 198 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{ID: "1234", Video: &openrtb2.Video{W: 300, H: 250}}}, 199 expected: []byte(`{"prebid":{"floors":{"floorrule":"test|123|xyz","floorrulevalue":5.5,"floorvalue":5.5}}}`), 200 }, 201 { 202 name: "Empty ImpExt", 203 matchedRule: "test|123|xyz", 204 floorRuleVal: 5.5, 205 floorVal: 5.5, 206 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{ID: "1234", Video: &openrtb2.Video{W: 300, H: 250}, Ext: json.RawMessage{}}}, 207 expected: []byte(`{"prebid":{"floors":{"floorrule":"test|123|xyz","floorrulevalue":5.5,"floorvalue":5.5}}}`), 208 }, 209 { 210 name: "With prebid Ext", 211 matchedRule: "banner|www.test.com|*", 212 floorRuleVal: 5.5, 213 floorVal: 15.5, 214 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{ID: "1234", Video: &openrtb2.Video{W: 300, H: 250}, Ext: []byte(`{"prebid": {"test": true}}`)}}, 215 expected: []byte(`{"prebid":{"floors":{"floorrule":"banner|www.test.com|*","floorrulevalue":5.5,"floorvalue":15.5}}}`), 216 }, 217 } 218 for _, tc := range testCases { 219 t.Run(tc.name, func(t *testing.T) { 220 updateImpExtWithFloorDetails(tc.imp, tc.matchedRule, tc.floorRuleVal, tc.floorVal) 221 _ = tc.imp.RebuildImp() 222 if tc.imp.Ext != nil { 223 assert.Equal(t, tc.imp.Ext, tc.expected, tc.name) 224 } 225 }) 226 } 227 } 228 229 func TestCreateRuleKeys(t *testing.T) { 230 testCases := []struct { 231 name string 232 floorSchema openrtb_ext.PriceFloorSchema 233 request *openrtb2.BidRequest 234 out []string 235 }{ 236 { 237 name: "CreateRule with banner mediatype, size and domain", 238 request: &openrtb2.BidRequest{ 239 Site: &openrtb2.Site{ 240 Domain: "www.test.com", 241 }, 242 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 243 Ext: json.RawMessage(`{"prebid": { "floors": {"data": {"currency": "USD","skipRate": 0,"schema": {"fields": [ "mediaType", "size", "domain" ] },"values": { "banner|300x250|www.website.com": 1.01, "banner|300x250|*": 2.01, "banner|300x600|www.website.com": 3.01, "banner|300x600|*": 4.01, "banner|728x90|www.website.com": 5.01, "banner|728x90|*": 6.01, "banner|*|www.website.com": 7.01, "banner|*|*": 8.01, "*|300x250|www.website.com": 9.01, "*|300x250|*": 10.01, "*|300x600|www.website.com": 11.01, "*|300x600|*": 12.01, "*|728x90|www.website.com": 13.01, "*|728x90|*": 14.01, "*|*|www.website.com": 15.01, "*|*|*": 16.01 }, "default": 1}}}}`), 244 }, 245 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "size", "domain"}}, 246 out: []string{"banner", "300x250", "www.test.com"}, 247 }, 248 { 249 name: "CreateRule with video mediatype, size and domain", 250 request: &openrtb2.BidRequest{ 251 Site: &openrtb2.Site{ 252 Domain: "www.test.com", 253 }, 254 Imp: []openrtb2.Imp{{ID: "1234", Video: &openrtb2.Video{W: 640, H: 480, Placement: 1}}}, 255 }, 256 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "size", "domain"}}, 257 out: []string{"video", "640x480", "www.test.com"}, 258 }, 259 { 260 name: "CreateRule with video mediatype, size and domain", 261 request: &openrtb2.BidRequest{ 262 Site: &openrtb2.Site{ 263 Domain: "www.test.com", 264 }, 265 Imp: []openrtb2.Imp{{ID: "1234", Video: &openrtb2.Video{W: 300, H: 250, Placement: 2}}}, 266 }, 267 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "size", "domain"}}, 268 out: []string{"video-outstream", "300x250", "www.test.com"}, 269 }, 270 { 271 name: "CreateRule with audio mediatype, adUnitCode and domain", 272 request: &openrtb2.BidRequest{ 273 Site: &openrtb2.Site{ 274 Domain: "www.test.com", 275 }, 276 Imp: []openrtb2.Imp{{ID: "1234", TagID: "tag123", Audio: &openrtb2.Audio{MaxDuration: 300}}}, 277 }, 278 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "adUnitCode", "siteDomain"}}, 279 out: []string{"audio", "tag123", "www.test.com"}, 280 }, 281 { 282 name: "CreateRule with audio mediatype, adUnitCode=* and domain", 283 request: &openrtb2.BidRequest{ 284 Site: &openrtb2.Site{ 285 Domain: "www.test.com", 286 }, 287 Imp: []openrtb2.Imp{{ID: "1234", Audio: &openrtb2.Audio{MaxDuration: 300}}}, 288 }, 289 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "adUnitCode", "siteDomain"}}, 290 out: []string{"audio", "*", "www.test.com"}, 291 }, 292 { 293 name: "CreateRule with native mediatype, bundle and domain", 294 request: &openrtb2.BidRequest{ 295 App: &openrtb2.App{ 296 Domain: "www.test.com", 297 Bundle: "bundle123", 298 }, 299 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}}, 300 }, 301 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "bundle", "siteDomain"}}, 302 out: []string{"native", "bundle123", "www.test.com"}, 303 }, 304 { 305 name: "CreateRule with native, banner mediatype, bundle and domain", 306 request: &openrtb2.BidRequest{ 307 App: &openrtb2.App{ 308 Domain: "www.test.com", 309 Bundle: "bundle123", 310 }, 311 Imp: []openrtb2.Imp{{ID: "1234", Audio: &openrtb2.Audio{MaxDuration: 300}, Native: &openrtb2.Native{Request: "Test"}}}, 312 }, 313 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"mediaType", "bundle", "siteDomain"}}, 314 out: []string{"*", "bundle123", "www.test.com"}, 315 }, 316 { 317 name: "CreateRule with channel, country, deviceType", 318 request: &openrtb2.BidRequest{ 319 App: &openrtb2.App{ 320 Publisher: &openrtb2.Publisher{ 321 Domain: "www.test.com", 322 }, 323 Bundle: "bundle123", 324 }, 325 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "tablet"}, 326 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}}, 327 Ext: json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`), 328 }, 329 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "country", "deviceType"}}, 330 out: []string{"chName", "USA", "tablet"}, 331 }, 332 { 333 name: "CreateRule with channel, country, deviceType=tablet", 334 request: &openrtb2.BidRequest{ 335 App: &openrtb2.App{ 336 Publisher: &openrtb2.Publisher{ 337 Domain: "www.test.com", 338 }, 339 Bundle: "bundle123", 340 }, 341 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "Windows NT touch"}, 342 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}}, 343 Ext: json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`), 344 }, 345 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "country", "deviceType"}}, 346 out: []string{"chName", "USA", "tablet"}, 347 }, 348 { 349 name: "CreateRule with channel, country, deviceType=desktop", 350 request: &openrtb2.BidRequest{ 351 App: &openrtb2.App{ 352 Publisher: &openrtb2.Publisher{ 353 Domain: "www.test.com", 354 }, 355 Bundle: "bundle123", 356 }, 357 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "Windows NT"}, 358 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}}, 359 Ext: json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`), 360 }, 361 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "country", "deviceType"}}, 362 out: []string{"chName", "USA", "desktop"}, 363 }, 364 { 365 name: "CreateRule with channel, country, deviceType=desktop", 366 request: &openrtb2.BidRequest{ 367 App: &openrtb2.App{ 368 Publisher: &openrtb2.Publisher{ 369 Domain: "www.test.com", 370 }, 371 Bundle: "bundle123", 372 }, 373 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "Windows NT"}, 374 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}}, 375 Ext: json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`), 376 }, 377 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "country", "deviceType"}}, 378 out: []string{"chName", "USA", "desktop"}, 379 }, 380 { 381 name: "CreateRule with channel, size, deviceType=desktop", 382 request: &openrtb2.BidRequest{ 383 App: &openrtb2.App{ 384 Publisher: &openrtb2.Publisher{ 385 Domain: "www.test.com", 386 }, 387 Bundle: "bundle123", 388 }, 389 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "SomeDevice"}, 390 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 100, H: 200}, {W: 200, H: 300}}}}}, 391 Ext: json.RawMessage(`{"prebid": {"test": "1}}`), 392 }, 393 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"channel", "size", "deviceType"}}, 394 out: []string{"*", "*", "desktop"}, 395 }, 396 { 397 name: "CreateRule with pubDomain, country, deviceType", 398 request: &openrtb2.BidRequest{ 399 App: &openrtb2.App{ 400 Publisher: &openrtb2.Publisher{ 401 Domain: "www.test.com", 402 }, 403 Bundle: "bundle123", 404 }, 405 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}, UA: "Phone"}, 406 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}}}, 407 Ext: json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`), 408 }, 409 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"pubDomain", "country", "deviceType"}}, 410 out: []string{"www.test.com", "USA", "phone"}, 411 }, 412 { 413 name: "CreateRule with pubDomain, gptSlot, deviceType", 414 request: &openrtb2.BidRequest{ 415 Site: &openrtb2.Site{ 416 Publisher: &openrtb2.Publisher{ 417 Domain: "www.test.com", 418 }, 419 }, 420 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}}, 421 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}, 422 Ext: json.RawMessage(`{"data": {"adserver": {"name": "gam","adslot": "adslot123"}, "pbadslot": "pbadslot123"}}`), 423 }}, 424 Ext: json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`), 425 }, 426 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"pubDomain", "gptSlot", "deviceType"}}, 427 out: []string{"www.test.com", "adslot123", "*"}, 428 }, 429 { 430 name: "CreateRule with pubDomain, gptSlot, deviceType", 431 request: &openrtb2.BidRequest{ 432 Site: &openrtb2.Site{ 433 Publisher: &openrtb2.Publisher{ 434 Domain: "www.test.com", 435 }, 436 }, 437 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}}, 438 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}, 439 Ext: json.RawMessage(`{"data": {"adserver": {"name": "test","adslot": "adslot123"}, "pbadslot": "pbadslot123"}}`), 440 }}, 441 Ext: json.RawMessage(`{"prebid": {"channel": {"name": "chName","version": "ver1"}}}`), 442 }, 443 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"pubDomain", "gptSlot", "deviceType"}}, 444 out: []string{"www.test.com", "pbadslot123", "*"}, 445 }, 446 { 447 name: "CreateRule with domain, adUnitCode, channel", 448 request: &openrtb2.BidRequest{ 449 App: &openrtb2.App{ 450 Publisher: &openrtb2.Publisher{ 451 Domain: "www.test.com", 452 }, 453 }, 454 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}}, 455 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}, 456 Ext: json.RawMessage(`{"data": {"adserver": {"name": "test","adslot": "adslot123"}, "pbadslot": "pbadslot123"}}`), 457 }}, 458 }, 459 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"domain", "adUnitCode", "channel"}}, 460 out: []string{"www.test.com", "pbadslot123", "*"}, 461 }, 462 { 463 name: "CreateRule with domain, adUnitCode, channel", 464 request: &openrtb2.BidRequest{ 465 App: &openrtb2.App{ 466 Publisher: &openrtb2.Publisher{ 467 Domain: "www.test.com", 468 }, 469 }, 470 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}}, 471 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{Request: "Test"}, 472 Ext: json.RawMessage(`{"gpid": "gpid_134"}`), 473 }}, 474 }, 475 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"domain", "adUnitCode", "channel"}}, 476 out: []string{"www.test.com", "gpid_134", "*"}, 477 }, 478 { 479 name: "CreateRule with domain, adUnitCode, channel", 480 request: &openrtb2.BidRequest{ 481 App: &openrtb2.App{ 482 Publisher: &openrtb2.Publisher{ 483 Domain: "www.test.com", 484 }, 485 }, 486 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}}, 487 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{}, Ext: json.RawMessage(`{"prebid": {"storedrequest": {"id": "storedid_123"}}}`)}}, 488 }, 489 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"domain", "adUnitCode", "channel"}}, 490 out: []string{"www.test.com", "storedid_123", "*"}, 491 }, 492 { 493 name: "CreateRule with domain, adUnitCode, channel", 494 request: &openrtb2.BidRequest{ 495 App: &openrtb2.App{ 496 Publisher: &openrtb2.Publisher{ 497 Domain: "www.test.com", 498 }, 499 }, 500 Device: &openrtb2.Device{Geo: &openrtb2.Geo{Country: "USA"}}, 501 Imp: []openrtb2.Imp{{ID: "1234", Native: &openrtb2.Native{}, Ext: json.RawMessage(`{"prebid": {"storedrequest": {"id": "storedid_123"}}}`)}}, 502 }, 503 floorSchema: openrtb_ext.PriceFloorSchema{Delimiter: "|", Fields: []string{"domain", "adUnitCode", "channel"}}, 504 out: []string{"www.test.com", "storedid_123", "*"}, 505 }, 506 } 507 for _, tc := range testCases { 508 t.Run(tc.name, func(t *testing.T) { 509 out := createRuleKey(tc.floorSchema, &openrtb_ext.RequestWrapper{BidRequest: tc.request}, &openrtb_ext.ImpWrapper{Imp: &tc.request.Imp[0]}) 510 assert.Equal(t, out, tc.out, tc.name) 511 }) 512 } 513 } 514 515 func TestShouldSkipFloors(t *testing.T) { 516 517 testCases := []struct { 518 name string 519 ModelGroupsSkipRate int 520 DataSkipRate int 521 RootSkipRate int 522 out bool 523 randomGen func(int) int 524 }{ 525 { 526 name: "ModelGroupsSkipRate=10 with skip = true", 527 ModelGroupsSkipRate: 10, 528 DataSkipRate: 0, 529 RootSkipRate: 0, 530 randomGen: func(i int) int { return 5 }, 531 out: true, 532 }, 533 { 534 name: "ModelGroupsSkipRate=100 with skip = true", 535 ModelGroupsSkipRate: 100, 536 DataSkipRate: 0, 537 RootSkipRate: 0, 538 randomGen: func(i int) int { return 5 }, 539 out: true, 540 }, 541 { 542 name: "ModelGroupsSkipRate=0 with skip = false", 543 ModelGroupsSkipRate: 0, 544 DataSkipRate: 0, 545 RootSkipRate: 0, 546 randomGen: func(i int) int { return 0 }, 547 out: false, 548 }, 549 { 550 name: "DataSkipRate=50 with with skip = true", 551 ModelGroupsSkipRate: 0, 552 DataSkipRate: 50, 553 RootSkipRate: 0, 554 randomGen: func(i int) int { return 40 }, 555 out: true, 556 }, 557 { 558 name: "RootSkipRate=50 with with skip = true", 559 ModelGroupsSkipRate: 0, 560 DataSkipRate: 0, 561 RootSkipRate: 60, 562 randomGen: func(i int) int { return 40 }, 563 out: true, 564 }, 565 { 566 name: "RootSkipRate=50 with with skip = false", 567 ModelGroupsSkipRate: 0, 568 DataSkipRate: 0, 569 RootSkipRate: 60, 570 randomGen: func(i int) int { return 70 }, 571 out: false, 572 }, 573 { 574 name: "RootSkipRate=100 with with skip = true", 575 ModelGroupsSkipRate: 0, 576 DataSkipRate: 0, 577 RootSkipRate: 100, 578 randomGen: func(i int) int { return 100 }, 579 out: true, 580 }, 581 } 582 for _, tc := range testCases { 583 t.Run(tc.name, func(t *testing.T) { 584 out := shouldSkipFloors(tc.ModelGroupsSkipRate, tc.DataSkipRate, tc.RootSkipRate, tc.randomGen) 585 assert.Equal(t, out, tc.out, tc.name) 586 }) 587 } 588 589 } 590 591 func TestSelectFloorModelGroup(t *testing.T) { 592 weightNilModelGroup := openrtb_ext.PriceFloorModelGroup{ModelWeight: nil} 593 weight01ModelGroup := openrtb_ext.PriceFloorModelGroup{ModelWeight: getIntPtr(1)} 594 weight25ModelGroup := openrtb_ext.PriceFloorModelGroup{ModelWeight: getIntPtr(25)} 595 weight50ModelGroup := openrtb_ext.PriceFloorModelGroup{ModelWeight: getIntPtr(50)} 596 597 testCases := []struct { 598 name string 599 ModelGroup []openrtb_ext.PriceFloorModelGroup 600 fn func(int) int 601 expectedModelGroup []openrtb_ext.PriceFloorModelGroup 602 }{ 603 { 604 name: "ModelGroup with default weight selection", 605 ModelGroup: []openrtb_ext.PriceFloorModelGroup{ 606 weightNilModelGroup, 607 }, 608 fn: func(i int) int { return 0 }, 609 expectedModelGroup: []openrtb_ext.PriceFloorModelGroup{ 610 weight01ModelGroup, 611 }, 612 }, 613 { 614 name: "ModelGroup with weight = 25 selection", 615 ModelGroup: []openrtb_ext.PriceFloorModelGroup{ 616 weight25ModelGroup, 617 weight50ModelGroup, 618 }, 619 fn: func(i int) int { return 5 }, 620 expectedModelGroup: []openrtb_ext.PriceFloorModelGroup{ 621 weight25ModelGroup, 622 }, 623 }, 624 { 625 name: "ModelGroup with weight = 50 selection", 626 ModelGroup: []openrtb_ext.PriceFloorModelGroup{ 627 weight50ModelGroup, 628 }, 629 fn: func(i int) int { return 55 }, 630 expectedModelGroup: []openrtb_ext.PriceFloorModelGroup{ 631 weight50ModelGroup, 632 }, 633 }, 634 { 635 name: "ModelGroup with weight = 25 selection", 636 ModelGroup: []openrtb_ext.PriceFloorModelGroup{ 637 weight25ModelGroup, 638 weight50ModelGroup, 639 }, 640 fn: func(i int) int { return 80 }, 641 expectedModelGroup: []openrtb_ext.PriceFloorModelGroup{ 642 weight25ModelGroup, 643 }, 644 }, 645 } 646 647 for _, tc := range testCases { 648 t.Run(tc.name, func(t *testing.T) { 649 resp := selectFloorModelGroup(tc.ModelGroup, tc.fn) 650 assert.Equal(t, resp, tc.expectedModelGroup) 651 }) 652 } 653 } 654 655 func TestGetMinFloorValue(t *testing.T) { 656 rates := map[string]map[string]float64{ 657 "USD": { 658 "INR": 81.17, 659 }, 660 } 661 662 type args struct { 663 floorExt *openrtb_ext.PriceFloorRules 664 imp openrtb2.Imp 665 conversions currency.Conversions 666 } 667 testCases := []struct { 668 name string 669 args args 670 want float64 671 want1 string 672 wantErr error 673 }{ 674 { 675 name: "Floor min is available in imp and floor ext", 676 args: args{ 677 floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 2.0, FloorMinCur: "INR", Data: &openrtb_ext.PriceFloorData{Currency: "INR"}}, 678 imp: openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "INR","floorMin":1.0}}}`)}, 679 }, 680 want: 1, 681 want1: "INR", 682 }, 683 { 684 name: "Floor min and floor min currency is available in imp ext only", 685 args: args{ 686 floorExt: &openrtb_ext.PriceFloorRules{}, 687 imp: openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "INR", "floorMin": 1.0}}}`)}, 688 }, 689 want: 0.0123, 690 want1: "USD", 691 }, 692 { 693 name: "Floor min is available in floor ext only", 694 args: args{ 695 floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 1.0, FloorMinCur: "EUR", Data: &openrtb_ext.PriceFloorData{Currency: "EUR"}}, 696 imp: openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{}}}`)}, 697 }, 698 want: 1.0, 699 want1: "EUR", 700 }, 701 { 702 name: "Floor min is available in floorExt and currency is available in imp", 703 args: args{ 704 floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 2.0, Data: &openrtb_ext.PriceFloorData{Currency: "INR"}}, 705 imp: openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "INR"}}}`)}, 706 }, 707 want: 2, 708 want1: "INR", 709 }, 710 { 711 name: "Floor min is available in ImpExt and currency is available in floorExt", 712 args: args{ 713 floorExt: &openrtb_ext.PriceFloorRules{FloorMinCur: "USD", Data: &openrtb_ext.PriceFloorData{Currency: "INR"}}, 714 imp: openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"FloorMin": 2.0}}}`)}, 715 }, 716 want: 162.34, 717 want1: "INR", 718 }, 719 { 720 name: "Floor Min and floor Currency are in Imp and only floor currency is available in floor ext", 721 args: args{ 722 floorExt: &openrtb_ext.PriceFloorRules{FloorMinCur: "USD"}, 723 imp: openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "USD","floorMin":1.0}}}`)}, 724 }, 725 want: 1, 726 want1: "USD", 727 }, 728 { 729 name: "Currency are different in floor ext and imp", 730 args: args{ 731 floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 0.0, FloorMinCur: "EUR", Data: &openrtb_ext.PriceFloorData{Currency: "INR"}}, 732 imp: openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "USD","floorMin":1.0}}}`)}, 733 }, 734 want: 81.17, 735 want1: "INR", 736 }, 737 { 738 name: "Floor min is 0 in imp ", 739 args: args{ 740 floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 2.0, FloorMinCur: "JPY", Data: &openrtb_ext.PriceFloorData{Currency: "INR"}}, 741 imp: openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "USD","floorMin":0.0}}}`)}, 742 }, 743 want: 162.34, 744 want1: "INR", 745 }, 746 { 747 name: "Floor Currency is empty in imp", 748 args: args{ 749 floorExt: &openrtb_ext.PriceFloorRules{FloorMin: 1.0, FloorMinCur: "EUR", Data: &openrtb_ext.PriceFloorData{Currency: "EUR"}}, 750 imp: openrtb2.Imp{Ext: json.RawMessage(`{"prebid":{"floors":{"floorMinCur": "","floorMin":-1.0}}}`)}, 751 }, 752 want: 1.0, 753 want1: "EUR", 754 }, 755 { 756 name: "Invalid input", 757 args: args{ 758 floorExt: &openrtb_ext.PriceFloorRules{FloorMinCur: "EUR", Data: &openrtb_ext.PriceFloorData{}}, 759 imp: openrtb2.Imp{Ext: json.RawMessage(`{`)}, 760 }, 761 want: 0.0, 762 want1: "", 763 wantErr: errors.New("Error in getting FloorMin value : 'unexpected end of JSON input'"), 764 }, 765 } 766 for _, tc := range testCases { 767 t.Run(tc.name, func(t *testing.T) { 768 got, got1, err := getMinFloorValue(tc.args.floorExt, &openrtb_ext.ImpWrapper{Imp: &tc.args.imp}, getCurrencyRates(rates)) 769 assert.Equal(t, tc.wantErr, err, tc.name) 770 assert.Equal(t, tc.want, got, tc.name) 771 assert.Equal(t, tc.want1, got1, tc.name) 772 }) 773 } 774 } 775 776 func TestSortCombinations(t *testing.T) { 777 type args struct { 778 comb [][]int 779 numSchemaFields int 780 } 781 tests := []struct { 782 name string 783 args args 784 expComb [][]int 785 }{ 786 { 787 name: "With schema fields = 3", 788 args: args{ 789 comb: [][]int{{0}, {1}, {2}}, 790 numSchemaFields: 3, 791 }, 792 expComb: [][]int{{2}, {1}, {0}}, 793 }, 794 { 795 name: "With schema fields = 3", 796 args: args{ 797 comb: [][]int{{0, 1}, {1, 2}, {0, 2}}, 798 numSchemaFields: 3, 799 }, 800 expComb: [][]int{{1, 2}, {0, 2}, {0, 1}}, 801 }, 802 { 803 name: "With schema fields = 4", 804 args: args{ 805 comb: [][]int{{0, 1, 2}, {1, 2, 3}, {0, 2, 3}, {0, 1, 3}}, 806 numSchemaFields: 3, 807 }, 808 expComb: [][]int{{1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2}}, 809 }, 810 } 811 for _, tt := range tests { 812 t.Run(tt.name, func(t *testing.T) { 813 sortCombinations(tt.args.comb, tt.args.numSchemaFields) 814 assert.Equal(t, tt.expComb, tt.args.comb) 815 }) 816 } 817 } 818 819 func TestGenerateCombinations(t *testing.T) { 820 821 tests := []struct { 822 name string 823 numSchemaFields int 824 numWildCard int 825 expComb [][]int 826 }{ 827 { 828 name: "With schema fields = 3, wildcard = 1", 829 numSchemaFields: 3, 830 numWildCard: 1, 831 expComb: [][]int{{0}, {1}, {2}}, 832 }, 833 { 834 name: "With schema fields = 3, wildcard = 2", 835 numSchemaFields: 3, 836 numWildCard: 2, 837 expComb: [][]int{{0, 1}, {0, 2}, {1, 2}}, 838 }, 839 { 840 name: "With schema fields = 3, wildcard = 3", 841 numSchemaFields: 3, 842 numWildCard: 3, 843 expComb: [][]int{{0, 1, 2}}, 844 }, 845 } 846 for _, tt := range tests { 847 t.Run(tt.name, func(t *testing.T) { 848 gotComb := generateCombinations(tt.numSchemaFields, tt.numWildCard) 849 assert.Equal(t, tt.expComb, gotComb) 850 }) 851 } 852 } 853 854 func TestGetDeviceType(t *testing.T) { 855 tests := []struct { 856 name string 857 request *openrtb2.BidRequest 858 want string 859 }{ 860 { 861 name: "user agent contains Phone", 862 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Phone Samsung Mobile; Win64; x64)"}}, 863 want: "phone", 864 }, 865 { 866 name: "user agent contains iPhone", 867 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Safari(iPhone Apple Mobile)"}}, 868 want: "phone", 869 }, 870 { 871 name: "user agent contains Mobile.*Android", 872 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Mobile Android; Win64; x64)"}}, 873 want: "phone", 874 }, 875 { 876 name: "user agent contains Android.*Mobile", 877 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Android Redmi Mobile; Win64; x64)"}}, 878 want: "phone", 879 }, 880 { 881 name: "user agent contains Mobile.*Android", 882 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Mobile pixel Android; Win64; x64)"}}, 883 want: "phone", 884 }, 885 { 886 name: "user agent contains Windows NT touch", 887 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Windows NT touch 10.0; Win64; x64)"}}, 888 want: "tablet", 889 }, 890 { 891 name: "user agent contains ipad", 892 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (ipad 13.10; Win64; x64)"}}, 893 want: "tablet", 894 }, 895 { 896 name: "user agent contains Window NT.*touch", 897 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0; Touch)"}}, 898 want: "tablet", 899 }, 900 { 901 name: "user agent contains touch.* Window NT", 902 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (touch realme Windows NT Win64; x64)"}}, 903 want: "tablet", 904 }, 905 { 906 name: "user agent contains Android", 907 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Android; Win64; x64)"}}, 908 want: "tablet", 909 }, 910 { 911 name: "user agent not matching phone or tablet", 912 request: &openrtb2.BidRequest{Device: &openrtb2.Device{UA: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}}, 913 want: "desktop", 914 }, 915 { 916 name: "empty user agent", 917 request: &openrtb2.BidRequest{Device: &openrtb2.Device{}}, 918 want: "*", 919 }, 920 } 921 for _, tt := range tests { 922 t.Run(tt.name, func(t *testing.T) { 923 got := getDeviceType(&openrtb_ext.RequestWrapper{BidRequest: tt.request}) 924 assert.Equal(t, tt.want, got) 925 }) 926 } 927 } 928 929 func TestGetAdUnitCode(t *testing.T) { 930 tests := []struct { 931 name string 932 imp *openrtb_ext.ImpWrapper 933 want string 934 }{ 935 { 936 name: "imp.ext.gpid", 937 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"gpid":"test_gpid"}`)}}, 938 want: "test_gpid", 939 }, 940 { 941 name: "imp.TagID", 942 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{TagID: "tag_1"}}, 943 want: "tag_1", 944 }, 945 { 946 name: "imp.ext.data.pbadslot", 947 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"data":{"pbadslot":"pbslot_1"}}`)}}, 948 want: "pbslot_1", 949 }, 950 { 951 name: "imp.ext.prebid.storedrequest.id", 952 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"prebid": {"storedrequest":{"id":"123"}}}`)}}, 953 want: "123", 954 }, 955 { 956 name: "empty adUnitCode", 957 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{}}, 958 want: "*", 959 }, 960 } 961 962 for _, tt := range tests { 963 t.Run(tt.name, func(t *testing.T) { 964 got := getAdUnitCode(tt.imp) 965 assert.Equal(t, tt.want, got) 966 }) 967 } 968 } 969 970 func TestGetGptSlot(t *testing.T) { 971 tests := []struct { 972 name string 973 imp *openrtb_ext.ImpWrapper 974 want string 975 }{ 976 { 977 name: "imp.ext.data.adserver.adslot", 978 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"data":{"adserver": {"name": "gam", "adslot": "slot_1"}}}`)}}, 979 want: "slot_1", 980 }, 981 { 982 name: "gptSlot = imp.ext.data.pbadslot", 983 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{Ext: json.RawMessage(`{"data":{"pbadslot":"pbslot_1"}}`)}}, 984 want: "pbslot_1", 985 }, 986 { 987 name: "empty gptSlot", 988 imp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{}}, 989 want: "*", 990 }, 991 } 992 for _, tt := range tests { 993 t.Run(tt.name, func(t *testing.T) { 994 got := getGptSlot(tt.imp) 995 assert.Equal(t, tt.want, got) 996 }) 997 } 998 } 999 1000 func TestGetSizeValue(t *testing.T) { 1001 tests := []struct { 1002 name string 1003 imp *openrtb2.Imp 1004 want string 1005 }{ 1006 { 1007 name: "banner: only one size exists in imp.banner.format", 1008 imp: &openrtb2.Imp{Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}, 1009 want: "300x250", 1010 }, 1011 { 1012 name: "banner: no imp.banner.format", 1013 imp: &openrtb2.Imp{Banner: &openrtb2.Banner{W: getInt64Ptr(320), H: getInt64Ptr(240)}}, 1014 want: "320x240", 1015 }, 1016 { 1017 name: "video: imp.video.w and imp.video.h present", 1018 imp: &openrtb2.Imp{Video: &openrtb2.Video{W: 120, H: 240}}, 1019 want: "120x240", 1020 }, 1021 { 1022 name: "banner: more than one size exists in imp.banner.format", 1023 imp: &openrtb2.Imp{Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}, {W: 200, H: 300}}}}, 1024 want: "*", 1025 }, 1026 { 1027 name: "Audo creative", 1028 imp: &openrtb2.Imp{Audio: &openrtb2.Audio{}}, 1029 want: "*", 1030 }, 1031 } 1032 for _, tt := range tests { 1033 t.Run(tt.name, func(t *testing.T) { 1034 got := getSizeValue(tt.imp) 1035 assert.Equal(t, tt.want, got) 1036 }) 1037 } 1038 } 1039 1040 func TestGetMediaType(t *testing.T) { 1041 tests := []struct { 1042 name string 1043 imp *openrtb2.Imp 1044 want string 1045 }{ 1046 { 1047 name: "more than one of these: imp.banner, imp.video, imp.native, imp.audio present", 1048 imp: &openrtb2.Imp{Video: &openrtb2.Video{W: 120, H: 240}, Banner: &openrtb2.Banner{W: getInt64Ptr(320), H: getInt64Ptr(240)}}, 1049 want: "*", 1050 }, 1051 { 1052 name: "only banner present", 1053 imp: &openrtb2.Imp{Banner: &openrtb2.Banner{W: getInt64Ptr(320), H: getInt64Ptr(240)}}, 1054 want: "banner", 1055 }, 1056 { 1057 name: "video-outstream present", 1058 imp: &openrtb2.Imp{Video: &openrtb2.Video{W: 120, H: 240, Placement: 2}}, 1059 want: "video-outstream", 1060 }, 1061 { 1062 name: "video-instream present", 1063 imp: &openrtb2.Imp{Video: &openrtb2.Video{W: 120, H: 240, Placement: 1}}, 1064 want: "video", 1065 }, 1066 { 1067 name: "only audio", 1068 imp: &openrtb2.Imp{Audio: &openrtb2.Audio{MinDuration: 10}}, 1069 want: "audio", 1070 }, 1071 { 1072 name: "only native", 1073 imp: &openrtb2.Imp{Native: &openrtb2.Native{Request: "test_req"}}, 1074 want: "native", 1075 }, 1076 } 1077 1078 for _, tt := range tests { 1079 t.Run(tt.name, func(t *testing.T) { 1080 got := getMediaType(tt.imp) 1081 assert.Equal(t, tt.want, got) 1082 }) 1083 } 1084 } 1085 1086 func TestGetSiteDomain(t *testing.T) { 1087 type args struct { 1088 request *openrtb_ext.RequestWrapper 1089 } 1090 tests := []struct { 1091 name string 1092 request *openrtb_ext.RequestWrapper 1093 want string 1094 }{ 1095 { 1096 name: "Site Domain present", 1097 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Domain: "abc.xyz.com"}}}, 1098 want: "abc.xyz.com", 1099 }, 1100 { 1101 name: "Site Domain not present", 1102 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{}}}, 1103 want: "*", 1104 }, 1105 { 1106 name: "App Domain present", 1107 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{Domain: "cde.rtu.com"}}}, 1108 want: "cde.rtu.com", 1109 }, 1110 { 1111 name: "App Domain not present", 1112 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{}}}, 1113 want: "*", 1114 }, 1115 } 1116 for _, tt := range tests { 1117 t.Run(tt.name, func(t *testing.T) { 1118 got := getSiteDomain(tt.request) 1119 assert.Equal(t, tt.want, got) 1120 }) 1121 } 1122 } 1123 1124 func TestGetPublisherDomain(t *testing.T) { 1125 type args struct { 1126 } 1127 tests := []struct { 1128 name string 1129 request *openrtb_ext.RequestWrapper 1130 want string 1131 }{ 1132 { 1133 name: "Site publisher domain present", 1134 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Publisher: &openrtb2.Publisher{Domain: "qwe.xyz.com"}}}}, 1135 want: "qwe.xyz.com", 1136 }, 1137 { 1138 name: "Site publisher domain not present", 1139 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Publisher: &openrtb2.Publisher{}}}}, 1140 want: "*", 1141 }, 1142 { 1143 name: "App publisher domain present", 1144 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{Publisher: &openrtb2.Publisher{Domain: "xyz.com"}}}}, 1145 want: "xyz.com", 1146 }, 1147 { 1148 name: "App publisher domain not present", 1149 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{}}}, 1150 want: "*", 1151 }, 1152 } 1153 for _, tt := range tests { 1154 t.Run(tt.name, func(t *testing.T) { 1155 got := getPublisherDomain(tt.request) 1156 assert.Equal(t, tt.want, got) 1157 }) 1158 } 1159 } 1160 1161 func TestGetDomain(t *testing.T) { 1162 type args struct { 1163 } 1164 tests := []struct { 1165 name string 1166 request *openrtb_ext.RequestWrapper 1167 want string 1168 }{ 1169 { 1170 name: "Site domain present", 1171 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Domain: "qwe.xyz.com", Publisher: &openrtb2.Publisher{Domain: "abc.xyz.com"}}}}, 1172 want: "qwe.xyz.com", 1173 }, 1174 { 1175 name: "Site publisher domain present", 1176 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Publisher: &openrtb2.Publisher{Domain: "abc.xyz.com"}}}}, 1177 want: "abc.xyz.com", 1178 }, 1179 { 1180 name: "Site domain not present", 1181 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{Site: &openrtb2.Site{Publisher: &openrtb2.Publisher{}}}}, 1182 want: "*", 1183 }, 1184 { 1185 name: "App publisher domain present", 1186 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{Domain: "abc.com", Publisher: &openrtb2.Publisher{Domain: "xyz.com"}}}}, 1187 want: "abc.com", 1188 }, 1189 { 1190 name: "App domain present", 1191 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{Publisher: &openrtb2.Publisher{Domain: "xyz.com"}}}}, 1192 want: "xyz.com", 1193 }, 1194 { 1195 name: "App domain not present", 1196 request: &openrtb_ext.RequestWrapper{BidRequest: &openrtb2.BidRequest{App: &openrtb2.App{}}}, 1197 want: "*", 1198 }, 1199 } 1200 for _, tt := range tests { 1201 t.Run(tt.name, func(t *testing.T) { 1202 got := getDomain(tt.request) 1203 assert.Equal(t, tt.want, got) 1204 }) 1205 } 1206 } 1207 1208 func getIntPtr(v int) *int { 1209 return &v 1210 } 1211 1212 func getInt64Ptr(v int64) *int64 { 1213 return &v 1214 }