github.com/prebid/prebid-server/v2@v2.18.0/floors/enforce_test.go (about) 1 package floors 2 3 import ( 4 "encoding/json" 5 "errors" 6 "reflect" 7 "testing" 8 9 "github.com/prebid/openrtb/v20/openrtb2" 10 "github.com/prebid/prebid-server/v2/config" 11 "github.com/prebid/prebid-server/v2/currency" 12 "github.com/prebid/prebid-server/v2/exchange/entities" 13 "github.com/prebid/prebid-server/v2/openrtb_ext" 14 "github.com/prebid/prebid-server/v2/util/ptrutil" 15 "github.com/stretchr/testify/assert" 16 ) 17 18 type convert struct { 19 } 20 21 func (c convert) GetRate(from string, to string) (float64, error) { 22 if from == to { 23 return 1, nil 24 } 25 26 if from == "USD" && to == "INR" { 27 return 77.59, nil 28 } else if from == "INR" && to == "USD" { 29 return 0.013, nil 30 } 31 return 0, errors.New("currency conversion not supported") 32 } 33 34 func (c convert) GetRates() *map[string]map[string]float64 { 35 return &map[string]map[string]float64{} 36 } 37 38 func TestIsValidImpBidfloorPresentInRequest(t *testing.T) { 39 40 tests := []struct { 41 name string 42 imp []openrtb2.Imp 43 want bool 44 }{ 45 { 46 imp: []openrtb2.Imp{{ID: "1234"}}, 47 want: false, 48 }, 49 { 50 imp: []openrtb2.Imp{{ID: "1234", BidFloor: 10, BidFloorCur: "USD"}}, 51 want: true, 52 }, 53 } 54 55 for _, tt := range tests { 56 got := isValidImpBidFloorPresent(tt.imp) 57 assert.Equal(t, tt.want, got, tt.name) 58 } 59 } 60 61 func TestEnforceFloorToBids(t *testing.T) { 62 type args struct { 63 bidRequestWrapper *openrtb_ext.RequestWrapper 64 seatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid 65 conversions currency.Conversions 66 enforceDealFloors bool 67 } 68 tests := []struct { 69 name string 70 args args 71 expEligibleBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid 72 expErrs []error 73 expRejectedBids []*entities.PbsOrtbSeatBid 74 }{ 75 { 76 name: "Floors enforcement disabled using enforcepbs = false", 77 args: args{ 78 bidRequestWrapper: func() *openrtb_ext.RequestWrapper { 79 bw := openrtb_ext.RequestWrapper{ 80 BidRequest: &openrtb2.BidRequest{ 81 ID: "some-request-id", 82 Imp: []openrtb2.Imp{ 83 {ID: "some-impression-id-1", BidFloor: 1.01, BidFloorCur: "USD"}, 84 {ID: "some-impression-id-2", BidFloor: 2.01, BidFloorCur: "USD"}, 85 }, 86 Ext: json.RawMessage(`{"prebid":{"floors":{"enforcement":{"enforcepbs":false}}}}`), 87 }, 88 } 89 bw.RebuildRequest() 90 return &bw 91 }(), 92 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 93 "pubmatic": { 94 Bids: []*entities.PbsOrtbBid{ 95 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 96 {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, 97 }, 98 Seat: "pubmatic", 99 Currency: "USD", 100 }, 101 "appnexus": { 102 Bids: []*entities.PbsOrtbBid{ 103 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.5, ImpID: "some-impression-id-1"}}, 104 {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, 105 }, 106 Seat: "appnexus", 107 Currency: "USD", 108 }, 109 }, 110 conversions: currency.Conversions(convert{}), 111 enforceDealFloors: false, 112 }, 113 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 114 "pubmatic": { 115 Bids: []*entities.PbsOrtbBid{ 116 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 117 {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, 118 }, 119 Seat: "pubmatic", 120 Currency: "USD", 121 }, 122 "appnexus": { 123 Bids: []*entities.PbsOrtbBid{ 124 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.5, ImpID: "some-impression-id-1"}}, 125 {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, 126 }, 127 Seat: "appnexus", 128 Currency: "USD", 129 }, 130 }, 131 expRejectedBids: []*entities.PbsOrtbSeatBid{}, 132 expErrs: []error{}, 133 }, 134 { 135 name: "Bids with price less than bidfloor", 136 args: args{ 137 bidRequestWrapper: func() *openrtb_ext.RequestWrapper { 138 bw := openrtb_ext.RequestWrapper{ 139 BidRequest: &openrtb2.BidRequest{ 140 ID: "some-request-id", 141 Imp: []openrtb2.Imp{ 142 {ID: "some-impression-id-1", BidFloor: 1.01, BidFloorCur: "USD"}, 143 {ID: "some-impression-id-2", BidFloor: 2.01, BidFloorCur: "USD"}, 144 }, 145 }, 146 } 147 bw.RebuildRequest() 148 return &bw 149 }(), 150 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 151 "pubmatic": { 152 Bids: []*entities.PbsOrtbBid{ 153 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 154 {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, 155 }, 156 Seat: "pubmatic", 157 Currency: "USD", 158 }, 159 "appnexus": { 160 Bids: []*entities.PbsOrtbBid{ 161 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.5, ImpID: "some-impression-id-1"}}, 162 {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, 163 }, 164 Seat: "appnexus", 165 Currency: "USD", 166 }, 167 }, 168 conversions: currency.Conversions(convert{}), 169 enforceDealFloors: false, 170 }, 171 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 172 "pubmatic": { 173 Bids: []*entities.PbsOrtbBid{ 174 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 175 {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, 176 }, 177 Seat: "pubmatic", 178 Currency: "USD", 179 }, 180 "appnexus": { 181 Bids: []*entities.PbsOrtbBid{ 182 {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, 183 }, 184 Seat: "appnexus", 185 Currency: "USD", 186 }, 187 }, 188 expRejectedBids: []*entities.PbsOrtbSeatBid{ 189 { 190 Seat: "appnexus", 191 Currency: "USD", 192 Bids: []*entities.PbsOrtbBid{ 193 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.5, ImpID: "some-impression-id-1"}}, 194 }, 195 }, 196 }, 197 expErrs: []error{}, 198 }, 199 { 200 name: "Bids with price less than bidfloor with floorsPrecision", 201 args: args{ 202 bidRequestWrapper: func() *openrtb_ext.RequestWrapper { 203 bw := openrtb_ext.RequestWrapper{ 204 BidRequest: &openrtb2.BidRequest{ 205 ID: "some-request-id", 206 Imp: []openrtb2.Imp{ 207 {ID: "some-impression-id-1", BidFloor: 1, BidFloorCur: "USD"}, 208 {ID: "some-impression-id-2", BidFloor: 2, BidFloorCur: "USD"}, 209 }, 210 }, 211 } 212 bw.RebuildRequest() 213 return &bw 214 }(), 215 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 216 "pubmatic": { 217 Bids: []*entities.PbsOrtbBid{ 218 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 0.998, ImpID: "some-impression-id-1"}}, 219 {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, 220 }, 221 Seat: "pubmatic", 222 Currency: "USD", 223 }, 224 "appnexus": { 225 Bids: []*entities.PbsOrtbBid{ 226 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.8, ImpID: "some-impression-id-1"}}, 227 {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, 228 }, 229 Seat: "appnexus", 230 Currency: "USD", 231 }, 232 }, 233 conversions: currency.Conversions(convert{}), 234 enforceDealFloors: false, 235 }, 236 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 237 "pubmatic": { 238 Bids: []*entities.PbsOrtbBid{ 239 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 0.998, ImpID: "some-impression-id-1"}}, 240 {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, 241 }, 242 Seat: "pubmatic", 243 Currency: "USD", 244 }, 245 "appnexus": { 246 Bids: []*entities.PbsOrtbBid{ 247 {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, 248 }, 249 Seat: "appnexus", 250 Currency: "USD", 251 }, 252 }, 253 expRejectedBids: []*entities.PbsOrtbSeatBid{ 254 { 255 Seat: "appnexus", 256 Currency: "USD", 257 Bids: []*entities.PbsOrtbBid{ 258 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.8, ImpID: "some-impression-id-1"}}, 259 }, 260 }, 261 }, 262 expErrs: []error{}, 263 }, 264 { 265 name: "Bids with different currency with enforceDealFloor true", 266 args: args{ 267 bidRequestWrapper: func() *openrtb_ext.RequestWrapper { 268 bw := openrtb_ext.RequestWrapper{ 269 BidRequest: &openrtb2.BidRequest{ 270 ID: "some-request-id", 271 Imp: []openrtb2.Imp{ 272 {ID: "some-impression-id-1", BidFloor: 60, BidFloorCur: "INR"}, 273 {ID: "some-impression-id-2", BidFloor: 100, BidFloorCur: "INR"}, 274 }, 275 }, 276 } 277 bw.RebuildRequest() 278 return &bw 279 }(), 280 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 281 "pubmatic": { 282 Bids: []*entities.PbsOrtbBid{ 283 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 284 {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, 285 }, 286 Seat: "pubmatic", 287 Currency: "USD", 288 }, 289 "appnexus": { 290 Bids: []*entities.PbsOrtbBid{ 291 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.5, ImpID: "some-impression-id-1"}}, 292 {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, 293 }, 294 Seat: "appnexus", 295 Currency: "USD", 296 }, 297 }, 298 conversions: currency.Conversions(convert{}), 299 enforceDealFloors: true, 300 }, 301 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 302 "pubmatic": { 303 Bids: []*entities.PbsOrtbBid{ 304 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 305 {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, 306 }, 307 Seat: "pubmatic", 308 Currency: "USD", 309 }, 310 "appnexus": { 311 Bids: []*entities.PbsOrtbBid{ 312 {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, 313 }, 314 Seat: "appnexus", 315 Currency: "USD", 316 }, 317 }, 318 expRejectedBids: []*entities.PbsOrtbSeatBid{ 319 { 320 Seat: "appnexus", 321 Currency: "USD", 322 Bids: []*entities.PbsOrtbBid{ 323 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.5, ImpID: "some-impression-id-1"}}, 324 }, 325 }, 326 }, 327 expErrs: []error{}, 328 }, 329 { 330 name: "Error in currency conversion", 331 args: args{ 332 bidRequestWrapper: func() *openrtb_ext.RequestWrapper { 333 bw := openrtb_ext.RequestWrapper{ 334 BidRequest: &openrtb2.BidRequest{ 335 ID: "some-request-id", 336 Cur: []string{"USD"}, 337 Imp: []openrtb2.Imp{{ID: "some-impression-id-1", BidFloor: 1.01}}, 338 }, 339 } 340 bw.RebuildRequest() 341 return &bw 342 }(), 343 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 344 "pubmatic": { 345 Bids: []*entities.PbsOrtbBid{ 346 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 347 }, 348 Currency: "EUR", 349 }, 350 }, 351 conversions: convert{}, 352 enforceDealFloors: true, 353 }, 354 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 355 "pubmatic": { 356 Bids: []*entities.PbsOrtbBid{}, 357 Currency: "EUR", 358 }, 359 }, 360 expRejectedBids: []*entities.PbsOrtbSeatBid{}, 361 expErrs: []error{errors.New("error in rate conversion from = EUR to with bidder pubmatic for impression id some-impression-id-1 and bid id some-bid-1 error = currency conversion not supported")}, 362 }, 363 { 364 name: "Bids with invalid impression ID", 365 args: args{ 366 bidRequestWrapper: func() *openrtb_ext.RequestWrapper { 367 bw := openrtb_ext.RequestWrapper{ 368 BidRequest: &openrtb2.BidRequest{ 369 ID: "some-request-id", 370 Imp: []openrtb2.Imp{ 371 {ID: "some-impression-id-2", BidFloor: 2.01, BidFloorCur: "USD"}, 372 }, 373 }, 374 } 375 bw.RebuildRequest() 376 return &bw 377 }(), 378 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 379 "pubmatic": { 380 Bids: []*entities.PbsOrtbBid{ 381 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-123"}}, 382 }, 383 Seat: "pubmatic", 384 Currency: "USD", 385 }, 386 }, 387 conversions: currency.Conversions(convert{}), 388 enforceDealFloors: false, 389 }, 390 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 391 "pubmatic": { 392 Bids: []*entities.PbsOrtbBid{}, 393 Seat: "pubmatic", 394 Currency: "USD", 395 }, 396 }, 397 expRejectedBids: []*entities.PbsOrtbSeatBid{}, 398 expErrs: []error{}, 399 }, 400 } 401 for _, tt := range tests { 402 seatbids, errs, rejBids := enforceFloorToBids(tt.args.bidRequestWrapper, tt.args.seatBids, tt.args.conversions, tt.args.enforceDealFloors) 403 assert.Equal(t, tt.expEligibleBids, seatbids, tt.name) 404 assert.Equal(t, tt.expErrs, errs, tt.name) 405 assert.Equal(t, tt.expRejectedBids, rejBids, tt.name) 406 } 407 } 408 409 func TestEnforce(t *testing.T) { 410 type args struct { 411 bidRequestWrapper *openrtb_ext.RequestWrapper 412 bidRequest *openrtb2.BidRequest 413 seatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid 414 priceFloorsCfg config.AccountPriceFloors 415 conversions currency.Conversions 416 } 417 tests := []struct { 418 name string 419 args args 420 expEligibleBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid 421 expErrs []error 422 expRejectedBids []*entities.PbsOrtbSeatBid 423 }{ 424 { 425 name: "Error in getting request extension", 426 args: args{ 427 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 428 BidRequest: &openrtb2.BidRequest{ 429 ID: "some-request-id", 430 Imp: []openrtb2.Imp{{ 431 ID: "some-impression-id-1", 432 Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}, 433 BidFloor: 5.01, 434 BidFloorCur: "USD", 435 }}, 436 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"data":{"currency":"USD","skiprate":100,"modelgroups":[{"modelversion":"version1","skiprate":10,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|*|*":20.01,"*|*|www.website1.com":16.01},"default":21}]},"enforcement":{"enforcepbs":true,"floordeals":false},"enabled":false,"skipped":false}}`), 437 }, 438 }, 439 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 440 "pubmatic": { 441 Bids: []*entities.PbsOrtbBid{ 442 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 4.5, ImpID: "some-impression-id-1"}}, 443 }, 444 Seat: "pubmatic", 445 Currency: "USD", 446 }, 447 }, 448 conversions: convert{}, 449 priceFloorsCfg: config.AccountPriceFloors{Enabled: false, EnforceFloorsRate: 100, EnforceDealFloors: true}, 450 }, 451 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 452 "pubmatic": { 453 Bids: []*entities.PbsOrtbBid{ 454 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 4.5, ImpID: "some-impression-id-1"}}, 455 }, 456 Seat: "pubmatic", 457 Currency: "USD", 458 }, 459 }, 460 expErrs: []error{errors.New("Error in getting request extension")}, 461 expRejectedBids: []*entities.PbsOrtbSeatBid{}, 462 }, 463 { 464 name: "Should not enforce floors when req.ext.prebid.floors.enabled = false", 465 args: args{ 466 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 467 BidRequest: &openrtb2.BidRequest{ 468 ID: "some-request-id", 469 Imp: []openrtb2.Imp{{ 470 ID: "some-impression-id-1", 471 Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}, 472 BidFloor: 5.01, 473 BidFloorCur: "USD", 474 }}, 475 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"data":{"currency":"USD","skiprate":100,"modelgroups":[{"modelversion":"version1","skiprate":10,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|*|*":20.01,"*|*|www.website1.com":16.01},"default":21}]},"enforcement":{"enforcepbs":true,"floordeals":false},"enabled":false}}}`), 476 }, 477 }, 478 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 479 "pubmatic": { 480 Bids: []*entities.PbsOrtbBid{ 481 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 4.5, ImpID: "some-impression-id-1"}}, 482 }, 483 Seat: "pubmatic", 484 Currency: "USD", 485 }, 486 }, 487 conversions: convert{}, 488 priceFloorsCfg: config.AccountPriceFloors{Enabled: true, EnforceFloorsRate: 100, EnforceDealFloors: true}, 489 }, 490 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 491 "pubmatic": { 492 Bids: []*entities.PbsOrtbBid{ 493 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 4.5, ImpID: "some-impression-id-1"}}, 494 }, 495 Seat: "pubmatic", 496 Currency: "USD", 497 }, 498 }, 499 expRejectedBids: []*entities.PbsOrtbSeatBid{}, 500 }, 501 { 502 name: "Should not enforce floors is disabled in account config", 503 args: args{ 504 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 505 BidRequest: &openrtb2.BidRequest{ 506 ID: "some-request-id", 507 Imp: []openrtb2.Imp{{ 508 ID: "some-impression-id-1", 509 Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}, {W: 300, H: 600}}}, 510 BidFloor: 5.01, 511 BidFloorCur: "USD", 512 }}, 513 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"data":{"currency":"USD","skiprate":100,"modelgroups":[{"modelversion":"version1","skiprate":10,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|*|*":20.01,"*|*|www.website1.com":16.01},"default":21}]},"enforcement":{"enforcepbs":true,"floordeals":false},"enabled":true}}}`), 514 }, 515 }, 516 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 517 "pubmatic": { 518 Bids: []*entities.PbsOrtbBid{ 519 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 520 }, 521 Seat: "pubmatic", 522 Currency: "USD", 523 }, 524 }, 525 conversions: convert{}, 526 priceFloorsCfg: config.AccountPriceFloors{Enabled: false, EnforceFloorsRate: 100, EnforceDealFloors: true}, 527 }, 528 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 529 "pubmatic": { 530 Bids: []*entities.PbsOrtbBid{ 531 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 532 }, 533 Seat: "pubmatic", 534 Currency: "USD", 535 }, 536 }, 537 expRejectedBids: []*entities.PbsOrtbSeatBid{}, 538 }, 539 { 540 name: "Should not enforce floors when req.ext.prebid.floors.enforcement.enforcepbs = false", 541 args: args{ 542 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 543 BidRequest: &openrtb2.BidRequest{ 544 ID: "some-request-id", 545 Imp: []openrtb2.Imp{{ 546 ID: "some-impression-id-1", 547 Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}, {W: 300, H: 600}}}, 548 BidFloor: 5.01, 549 BidFloorCur: "USD", 550 }}, 551 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"data":{"currency":"USD","skiprate":100,"modelgroups":[{"modelversion":"version1","skiprate":10,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|*|*":20.01,"*|*|www.website1.com":16.01},"default":21}]},"enforcement":{"enforcepbs":false,"floordeals":false},"enabled":true,"skipped":false}}}`), 552 }, 553 }, 554 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 555 "pubmatic": { 556 Bids: []*entities.PbsOrtbBid{ 557 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 558 }, 559 Seat: "pubmatic", 560 Currency: "USD", 561 }, 562 }, 563 conversions: convert{}, 564 priceFloorsCfg: config.AccountPriceFloors{Enabled: true, EnforceFloorsRate: 100, EnforceDealFloors: true}, 565 }, 566 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 567 "pubmatic": { 568 Bids: []*entities.PbsOrtbBid{ 569 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}, BidFloors: &openrtb_ext.ExtBidPrebidFloors{FloorValue: 5.01, FloorCurrency: "USD"}}, 570 }, 571 Seat: "pubmatic", 572 Currency: "USD", 573 }, 574 }, 575 expErrs: []error{}, 576 expRejectedBids: []*entities.PbsOrtbSeatBid{}, 577 }, 578 { 579 name: "Should not enforce floors when req.ext.prebid.floors.skipped = true", 580 args: args{ 581 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 582 BidRequest: &openrtb2.BidRequest{ 583 ID: "some-request-id", 584 Imp: []openrtb2.Imp{{ 585 ID: "some-impression-id-1", 586 Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}, {W: 300, H: 600}}}, 587 BidFloor: 5.01, 588 BidFloorCur: "USD", 589 }}, 590 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"data":{"currency":"USD","skiprate":100,"modelgroups":[{"modelversion":"version1","skiprate":10,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|*|*":20.01,"*|*|www.website1.com":16.01},"default":21}]},"enforcement":{"enforcepbs":true,"floordeals":false},"enabled":true,"skipped":true}}}`), 591 }, 592 }, 593 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 594 "pubmatic": { 595 Bids: []*entities.PbsOrtbBid{ 596 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 597 }, 598 Seat: "pubmatic", 599 Currency: "USD", 600 }, 601 }, 602 conversions: convert{}, 603 priceFloorsCfg: config.AccountPriceFloors{Enabled: true, EnforceFloorsRate: 100, EnforceDealFloors: true}, 604 }, 605 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 606 "pubmatic": { 607 Bids: []*entities.PbsOrtbBid{ 608 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, ImpID: "some-impression-id-1"}}, 609 }, 610 Seat: "pubmatic", 611 Currency: "USD", 612 }, 613 }, 614 expRejectedBids: []*entities.PbsOrtbSeatBid{}, 615 }, 616 { 617 name: "Should enforce floors for deals, ext.prebid.floors.enforcement.floorDeals = true and floors enabled = true", 618 args: args{ 619 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 620 BidRequest: &openrtb2.BidRequest{ 621 ID: "some-request-id", 622 Imp: []openrtb2.Imp{{ 623 ID: "some-impression-id-1", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}, BidFloor: 20.01, BidFloorCur: "USD", 624 }}, 625 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"data":{"currency":"USD","skiprate":100,"modelgroups":[{"modelversion":"version1","skiprate":10,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|*|*":20.01,"*|*|www.website1.com":16.01},"default":21}]},"enforcement":{"enforcepbs":true,"floordeals":true},"enabled":true}}}`), 626 }, 627 }, 628 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 629 "pubmatic": { 630 Bids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, DealID: "deal_Id_1", ImpID: "some-impression-id-1"}}}, 631 Seat: "pubmatic", 632 Currency: "USD", 633 }, 634 "appnexus": { 635 Bids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.5, DealID: "deal_Id_3", ImpID: "some-impression-id-1"}}}, 636 Seat: "appnexus", 637 Currency: "USD", 638 }, 639 }, 640 conversions: convert{}, 641 priceFloorsCfg: config.AccountPriceFloors{Enabled: true, EnforceFloorsRate: 0, EnforceDealFloors: true}, 642 }, 643 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 644 "pubmatic": { 645 Bids: []*entities.PbsOrtbBid{}, 646 Seat: "pubmatic", 647 Currency: "USD", 648 }, 649 "appnexus": { 650 Bids: []*entities.PbsOrtbBid{}, 651 Seat: "appnexus", 652 Currency: "USD", 653 }, 654 }, 655 expRejectedBids: []*entities.PbsOrtbSeatBid{ 656 { 657 Seat: "pubmatic", 658 Currency: "USD", 659 Bids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, DealID: "deal_Id_1", ImpID: "some-impression-id-1"}, BidFloors: &openrtb_ext.ExtBidPrebidFloors{FloorCurrency: "USD", FloorValue: 20.01}}}, 660 }, 661 { 662 Seat: "appnexus", 663 Currency: "USD", 664 Bids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.5, DealID: "deal_Id_3", ImpID: "some-impression-id-1"}, BidFloors: &openrtb_ext.ExtBidPrebidFloors{FloorCurrency: "USD", FloorValue: 20.01}}}, 665 }, 666 }, 667 expErrs: []error{}, 668 }, 669 { 670 name: "Should enforce floors when imp.bidfloor provided and enforcepbs not provided", 671 args: args{ 672 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 673 BidRequest: &openrtb2.BidRequest{ 674 ID: "some-request-id", 675 Imp: []openrtb2.Imp{{ 676 ID: "some-impression-id-1", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}, BidFloor: 5.01, BidFloorCur: "USD", 677 }}, 678 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1}}}`), 679 }, 680 }, 681 seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 682 "pubmatic": { 683 Bids: []*entities.PbsOrtbBid{ 684 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, DealID: "deal_Id_1", ImpID: "some-impression-id-1"}}, 685 }, 686 Seat: "pubmatic", 687 Currency: "USD", 688 }, 689 "appnexus": { 690 Bids: []*entities.PbsOrtbBid{ 691 {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 4.5, ImpID: "some-impression-id-1"}}, 692 }, 693 Seat: "appnexus", 694 Currency: "USD", 695 }, 696 }, 697 conversions: convert{}, 698 priceFloorsCfg: config.AccountPriceFloors{Enabled: true, EnforceFloorsRate: 0, EnforceDealFloors: false}, 699 }, 700 expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ 701 "pubmatic": { 702 Bids: []*entities.PbsOrtbBid{ 703 {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 1.2, DealID: "deal_Id_1", ImpID: "some-impression-id-1"}, BidFloors: &openrtb_ext.ExtBidPrebidFloors{FloorValue: 5.01, FloorCurrency: "USD"}}, 704 }, 705 Seat: "pubmatic", 706 Currency: "USD", 707 }, 708 "appnexus": { 709 Bids: []*entities.PbsOrtbBid{}, 710 Seat: "appnexus", 711 Currency: "USD", 712 }, 713 }, 714 expRejectedBids: []*entities.PbsOrtbSeatBid{ 715 { 716 Seat: "appnexus", 717 Currency: "USD", 718 Bids: []*entities.PbsOrtbBid{{Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 4.5, ImpID: "some-impression-id-1"}, BidFloors: &openrtb_ext.ExtBidPrebidFloors{FloorValue: 5.01, FloorCurrency: "USD"}}}, 719 }, 720 }, 721 expErrs: []error{}, 722 }, 723 } 724 for _, tt := range tests { 725 actEligibleBids, actErrs, actRejecteBids := Enforce(tt.args.bidRequestWrapper, tt.args.seatBids, config.Account{PriceFloors: tt.args.priceFloorsCfg}, tt.args.conversions) 726 assert.Equal(t, tt.expErrs, actErrs, tt.name) 727 assert.ElementsMatch(t, tt.expRejectedBids, actRejecteBids, tt.name) 728 729 if !reflect.DeepEqual(tt.expEligibleBids, actEligibleBids) { 730 assert.Failf(t, "eligible bids don't match", "Expected: %v, Got: %v", tt.expEligibleBids, actEligibleBids) 731 } 732 } 733 } 734 735 func TestUpdateBidExtWithFloors(t *testing.T) { 736 type args struct { 737 reqImp *openrtb_ext.ImpWrapper 738 bid *entities.PbsOrtbBid 739 floorCurrency string 740 } 741 tests := []struct { 742 name string 743 expBidFloor *openrtb_ext.ExtBidPrebidFloors 744 args args 745 }{ 746 { 747 name: "Empty prebid extension in imp.ext", 748 args: args{ 749 reqImp: &openrtb_ext.ImpWrapper{ 750 Imp: &openrtb2.Imp{BidFloor: 10, BidFloorCur: "USD"}, 751 }, 752 bid: &entities.PbsOrtbBid{ 753 Bid: &openrtb2.Bid{ 754 Price: 10.10, 755 AdM: "Adm", 756 }, 757 }, 758 floorCurrency: "USD", 759 }, 760 expBidFloor: &openrtb_ext.ExtBidPrebidFloors{ 761 FloorValue: 10, 762 FloorCurrency: "USD", 763 }, 764 }, 765 { 766 name: "Valid prebid extension in imp.ext", 767 args: args{ 768 reqImp: &openrtb_ext.ImpWrapper{Imp: &openrtb2.Imp{ID: "1234", Video: &openrtb2.Video{W: ptrutil.ToPtr[int64](300), H: ptrutil.ToPtr[int64](250)}, Ext: []byte(`{"prebid":{"floors":{"floorrule":"test|123|xyz","floorrulevalue":5.5,"floorvalue":5.5}}}`)}}, 769 bid: &entities.PbsOrtbBid{ 770 Bid: &openrtb2.Bid{ 771 Price: 10.10, 772 AdM: "Adm", 773 }, 774 }, 775 floorCurrency: "USD", 776 }, 777 expBidFloor: &openrtb_ext.ExtBidPrebidFloors{ 778 FloorRule: "test|123|xyz", 779 FloorRuleValue: 5.5, 780 FloorValue: 5.5, 781 FloorCurrency: "USD", 782 }, 783 }, 784 } 785 for _, tt := range tests { 786 updateBidExtWithFloors(tt.args.reqImp, tt.args.bid, tt.args.floorCurrency) 787 assert.Equal(t, tt.expBidFloor, tt.args.bid.BidFloors, tt.name) 788 } 789 } 790 791 func TestIsEnforcementEnabledForRequest(t *testing.T) { 792 tests := []struct { 793 name string 794 reqExt *openrtb_ext.RequestExt 795 want bool 796 }{ 797 { 798 name: "Req.ext not provided", 799 reqExt: func() *openrtb_ext.RequestExt { 800 return &openrtb_ext.RequestExt{} 801 }(), 802 want: true, 803 }, 804 { 805 name: "Req.ext provided EnforcePBS = false", 806 reqExt: func() *openrtb_ext.RequestExt { 807 reqExt := openrtb_ext.RequestExt{} 808 prebidExt := openrtb_ext.ExtRequestPrebid{ 809 Floors: &openrtb_ext.PriceFloorRules{ 810 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 811 EnforcePBS: ptrutil.ToPtr(false), 812 }, 813 }, 814 } 815 reqExt.SetPrebid(&prebidExt) 816 return &reqExt 817 }(), 818 want: false, 819 }, 820 { 821 name: "Req.ext provided EnforcePBS = true", 822 reqExt: func() *openrtb_ext.RequestExt { 823 reqExt := openrtb_ext.RequestExt{} 824 prebidExt := openrtb_ext.ExtRequestPrebid{ 825 Floors: &openrtb_ext.PriceFloorRules{ 826 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 827 EnforcePBS: ptrutil.ToPtr(true), 828 }, 829 }, 830 } 831 reqExt.SetPrebid(&prebidExt) 832 return &reqExt 833 }(), 834 want: true, 835 }, 836 } 837 for _, tt := range tests { 838 got := isEnforcementEnabled(tt.reqExt) 839 assert.Equal(t, tt.want, got, tt.name) 840 } 841 } 842 843 func TestIsSignalingSkipped(t *testing.T) { 844 tests := []struct { 845 name string 846 reqExt *openrtb_ext.RequestExt 847 want bool 848 }{ 849 { 850 name: "Req.ext nil", 851 reqExt: func() *openrtb_ext.RequestExt { 852 return nil 853 }(), 854 want: false, 855 }, 856 { 857 name: "Req.ext provided without prebid ext", 858 reqExt: func() *openrtb_ext.RequestExt { 859 return &openrtb_ext.RequestExt{} 860 }(), 861 want: false, 862 }, 863 { 864 name: "Req.ext provided without Floors in prebid ext", 865 reqExt: func() *openrtb_ext.RequestExt { 866 reqExt := openrtb_ext.RequestExt{} 867 prebidExt := openrtb_ext.ExtRequestPrebid{} 868 reqExt.SetPrebid(&prebidExt) 869 return &reqExt 870 }(), 871 want: false, 872 }, 873 { 874 name: "Req.ext provided Skipped = true", 875 reqExt: func() *openrtb_ext.RequestExt { 876 reqExt := openrtb_ext.RequestExt{} 877 prebidExt := openrtb_ext.ExtRequestPrebid{ 878 Floors: &openrtb_ext.PriceFloorRules{ 879 Skipped: ptrutil.ToPtr(true), 880 }, 881 } 882 reqExt.SetPrebid(&prebidExt) 883 return &reqExt 884 }(), 885 want: true, 886 }, 887 { 888 name: "Req.ext provided Skipped = false", 889 reqExt: func() *openrtb_ext.RequestExt { 890 reqExt := openrtb_ext.RequestExt{} 891 prebidExt := openrtb_ext.ExtRequestPrebid{ 892 Floors: &openrtb_ext.PriceFloorRules{ 893 Skipped: ptrutil.ToPtr(false), 894 }, 895 } 896 reqExt.SetPrebid(&prebidExt) 897 return &reqExt 898 }(), 899 want: false, 900 }, 901 } 902 for _, tt := range tests { 903 got := isSignalingSkipped(tt.reqExt) 904 assert.Equal(t, tt.want, got, tt.name) 905 } 906 } 907 908 func TestGetEnforceRateRequest(t *testing.T) { 909 tests := []struct { 910 name string 911 reqExt *openrtb_ext.RequestExt 912 want int 913 }{ 914 { 915 name: "Req.ext not provided", 916 reqExt: func() *openrtb_ext.RequestExt { 917 return &openrtb_ext.RequestExt{} 918 }(), 919 want: 0, 920 }, 921 { 922 name: "Req.ext.prebid.floors provided with EnforceRate = 0", 923 reqExt: func() *openrtb_ext.RequestExt { 924 reqExt := openrtb_ext.RequestExt{} 925 prebidExt := openrtb_ext.ExtRequestPrebid{ 926 Floors: &openrtb_ext.PriceFloorRules{ 927 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 928 EnforceRate: 0, 929 }, 930 }, 931 } 932 reqExt.SetPrebid(&prebidExt) 933 return &reqExt 934 }(), 935 want: 0, 936 }, 937 { 938 name: "Req.ext.prebid.floors provided with EnforceRate = 50", 939 reqExt: func() *openrtb_ext.RequestExt { 940 reqExt := openrtb_ext.RequestExt{} 941 prebidExt := openrtb_ext.ExtRequestPrebid{ 942 Floors: &openrtb_ext.PriceFloorRules{ 943 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 944 EnforceRate: 50, 945 }, 946 }, 947 } 948 reqExt.SetPrebid(&prebidExt) 949 return &reqExt 950 }(), 951 want: 50, 952 }, 953 { 954 name: "Req.ext.prebid.floors provided with EnforceRate = 100", 955 reqExt: func() *openrtb_ext.RequestExt { 956 reqExt := openrtb_ext.RequestExt{} 957 prebidExt := openrtb_ext.ExtRequestPrebid{ 958 Floors: &openrtb_ext.PriceFloorRules{ 959 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 960 EnforceRate: 100, 961 }, 962 }, 963 } 964 reqExt.SetPrebid(&prebidExt) 965 return &reqExt 966 }(), 967 want: 100, 968 }, 969 } 970 for _, tt := range tests { 971 got := getEnforceRateRequest(tt.reqExt) 972 assert.Equal(t, tt.want, got, tt.name) 973 } 974 } 975 976 func TestGetEnforceDealsFlag(t *testing.T) { 977 tests := []struct { 978 name string 979 reqExt *openrtb_ext.RequestExt 980 want bool 981 }{ 982 { 983 name: "Req.ext not provided", 984 reqExt: func() *openrtb_ext.RequestExt { 985 return &openrtb_ext.RequestExt{} 986 }(), 987 want: false, 988 }, 989 { 990 name: "Req.ext.prebid.floors provided, enforceDeals not provided", 991 reqExt: func() *openrtb_ext.RequestExt { 992 reqExt := openrtb_ext.RequestExt{} 993 prebidExt := openrtb_ext.ExtRequestPrebid{ 994 Floors: &openrtb_ext.PriceFloorRules{ 995 Enforcement: &openrtb_ext.PriceFloorEnforcement{}, 996 }, 997 } 998 reqExt.SetPrebid(&prebidExt) 999 return &reqExt 1000 }(), 1001 want: false, 1002 }, 1003 { 1004 name: "Req.ext.prebid.floors provided with enforceDeals = false", 1005 reqExt: func() *openrtb_ext.RequestExt { 1006 reqExt := openrtb_ext.RequestExt{} 1007 prebidExt := openrtb_ext.ExtRequestPrebid{ 1008 Floors: &openrtb_ext.PriceFloorRules{ 1009 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 1010 FloorDeals: ptrutil.ToPtr(false), 1011 }, 1012 }, 1013 } 1014 reqExt.SetPrebid(&prebidExt) 1015 return &reqExt 1016 }(), 1017 want: false, 1018 }, 1019 { 1020 name: "Req.ext.prebid.floors provided with enforceDeals = true", 1021 reqExt: func() *openrtb_ext.RequestExt { 1022 reqExt := openrtb_ext.RequestExt{} 1023 prebidExt := openrtb_ext.ExtRequestPrebid{ 1024 Floors: &openrtb_ext.PriceFloorRules{ 1025 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 1026 FloorDeals: ptrutil.ToPtr(true), 1027 }, 1028 }, 1029 } 1030 reqExt.SetPrebid(&prebidExt) 1031 return &reqExt 1032 }(), 1033 want: true, 1034 }, 1035 } 1036 for _, tt := range tests { 1037 got := getEnforceDealsFlag(tt.reqExt) 1038 assert.Equal(t, tt.want, got, tt.name) 1039 } 1040 } 1041 1042 func TestIsSatisfiedByEnforceRate(t *testing.T) { 1043 type args struct { 1044 reqExt *openrtb_ext.RequestExt 1045 configEnforceRate int 1046 f func(int) int 1047 } 1048 tests := []struct { 1049 name string 1050 args args 1051 want bool 1052 }{ 1053 { 1054 name: "With EnforceRate = 50", 1055 args: args{ 1056 reqExt: func() *openrtb_ext.RequestExt { 1057 reqExt := openrtb_ext.RequestExt{} 1058 prebidExt := openrtb_ext.ExtRequestPrebid{ 1059 Floors: &openrtb_ext.PriceFloorRules{ 1060 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 1061 EnforceRate: 50, 1062 EnforcePBS: ptrutil.ToPtr(true), 1063 }, 1064 }, 1065 } 1066 reqExt.SetPrebid(&prebidExt) 1067 return &reqExt 1068 }(), 1069 configEnforceRate: 100, 1070 f: func(n int) int { 1071 return n 1072 }, 1073 }, 1074 want: false, 1075 }, 1076 { 1077 name: "With EnforceRate = 100", 1078 args: args{ 1079 reqExt: func() *openrtb_ext.RequestExt { 1080 reqExt := openrtb_ext.RequestExt{} 1081 prebidExt := openrtb_ext.ExtRequestPrebid{ 1082 Floors: &openrtb_ext.PriceFloorRules{ 1083 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 1084 EnforceRate: 100, 1085 EnforcePBS: ptrutil.ToPtr(true), 1086 }, 1087 }, 1088 } 1089 reqExt.SetPrebid(&prebidExt) 1090 return &reqExt 1091 }(), 1092 configEnforceRate: 100, 1093 f: func(n int) int { 1094 return n - 1 1095 }, 1096 }, 1097 want: true, 1098 }, 1099 { 1100 name: "With configEnforceRate = 0", 1101 args: args{ 1102 reqExt: func() *openrtb_ext.RequestExt { 1103 reqExt := openrtb_ext.RequestExt{} 1104 prebidExt := openrtb_ext.ExtRequestPrebid{ 1105 Floors: &openrtb_ext.PriceFloorRules{ 1106 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 1107 EnforceRate: 0, 1108 EnforcePBS: ptrutil.ToPtr(true), 1109 }, 1110 }, 1111 } 1112 reqExt.SetPrebid(&prebidExt) 1113 return &reqExt 1114 }(), 1115 configEnforceRate: 0, 1116 f: func(n int) int { 1117 return n - 1 1118 }, 1119 }, 1120 want: true, 1121 }, 1122 } 1123 for _, tt := range tests { 1124 got := isSatisfiedByEnforceRate(tt.args.reqExt, tt.args.configEnforceRate, tt.args.f) 1125 assert.Equal(t, tt.want, got, tt.name) 1126 } 1127 } 1128 1129 func TestUpdateEnforcePBS(t *testing.T) { 1130 type args struct { 1131 enforceFloors bool 1132 reqExt *openrtb_ext.RequestExt 1133 } 1134 tests := []struct { 1135 name string 1136 args args 1137 want bool 1138 }{ 1139 { 1140 name: "Enforce PBS is true in request and to be updated = true", 1141 args: args{ 1142 enforceFloors: true, 1143 reqExt: func() *openrtb_ext.RequestExt { 1144 reqExt := openrtb_ext.RequestExt{} 1145 prebidExt := openrtb_ext.ExtRequestPrebid{ 1146 Floors: &openrtb_ext.PriceFloorRules{ 1147 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 1148 EnforcePBS: ptrutil.ToPtr(true), 1149 }, 1150 }, 1151 } 1152 reqExt.SetPrebid(&prebidExt) 1153 return &reqExt 1154 }(), 1155 }, 1156 want: false, 1157 }, 1158 { 1159 name: "Enforce PBS is false in request and to be updated = true", 1160 args: args{ 1161 enforceFloors: true, 1162 reqExt: func() *openrtb_ext.RequestExt { 1163 reqExt := openrtb_ext.RequestExt{} 1164 prebidExt := openrtb_ext.ExtRequestPrebid{ 1165 Floors: &openrtb_ext.PriceFloorRules{ 1166 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 1167 EnforcePBS: ptrutil.ToPtr(false), 1168 }, 1169 }, 1170 } 1171 reqExt.SetPrebid(&prebidExt) 1172 return &reqExt 1173 }(), 1174 }, 1175 want: false, 1176 }, 1177 { 1178 name: "Enforce PBS is true in request and to be updated = false", 1179 args: args{ 1180 enforceFloors: false, 1181 reqExt: func() *openrtb_ext.RequestExt { 1182 reqExt := openrtb_ext.RequestExt{} 1183 prebidExt := openrtb_ext.ExtRequestPrebid{ 1184 Floors: &openrtb_ext.PriceFloorRules{ 1185 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 1186 EnforcePBS: ptrutil.ToPtr(true), 1187 }, 1188 }, 1189 } 1190 reqExt.SetPrebid(&prebidExt) 1191 return &reqExt 1192 }(), 1193 }, 1194 want: true, 1195 }, 1196 { 1197 name: "empty prebid ext and to be updated = false", 1198 args: args{enforceFloors: false, 1199 reqExt: func() *openrtb_ext.RequestExt { 1200 return &openrtb_ext.RequestExt{} 1201 }(), 1202 }, 1203 want: true, 1204 }, 1205 { 1206 name: "empty prebid ext and to be updated = true", 1207 args: args{enforceFloors: true, 1208 reqExt: func() *openrtb_ext.RequestExt { 1209 reqExt := openrtb_ext.RequestExt{} 1210 prebidExt := openrtb_ext.ExtRequestPrebid{} 1211 reqExt.SetPrebid(&prebidExt) 1212 return &reqExt 1213 }(), 1214 }, 1215 want: true, 1216 }, 1217 } 1218 for _, tt := range tests { 1219 t.Run(tt.name, func(t *testing.T) { 1220 got := updateEnforcePBS(tt.args.enforceFloors, tt.args.reqExt) 1221 assert.Equal(t, tt.want, got, tt.name) 1222 }) 1223 } 1224 }