github.com/prebid/prebid-server@v0.275.0/floors/floors_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/config" 10 "github.com/prebid/prebid-server/currency" 11 "github.com/prebid/prebid-server/openrtb_ext" 12 "github.com/stretchr/testify/assert" 13 ) 14 15 func TestIsRequestEnabledWithFloor(t *testing.T) { 16 FalseFlag := false 17 TrueFlag := true 18 19 testCases := []struct { 20 name string 21 in *openrtb_ext.ExtRequest 22 out bool 23 }{ 24 { 25 name: "Request With Nil Floors", 26 in: &openrtb_ext.ExtRequest{}, 27 out: true, 28 }, 29 { 30 name: "Request With Floors Disabled", 31 in: &openrtb_ext.ExtRequest{Prebid: openrtb_ext.ExtRequestPrebid{Floors: &openrtb_ext.PriceFloorRules{Enabled: &FalseFlag}}}, 32 out: false, 33 }, 34 { 35 name: "Request With Floors Enabled", 36 in: &openrtb_ext.ExtRequest{Prebid: openrtb_ext.ExtRequestPrebid{Floors: &openrtb_ext.PriceFloorRules{Enabled: &TrueFlag}}}, 37 out: true, 38 }, 39 } 40 for _, tc := range testCases { 41 t.Run(tc.name, func(t *testing.T) { 42 out := tc.in.Prebid.Floors.GetEnabled() 43 assert.Equal(t, out, tc.out, tc.name) 44 }) 45 } 46 } 47 48 func getCurrencyRates(rates map[string]map[string]float64) currency.Conversions { 49 return currency.NewRates(rates) 50 } 51 52 func TestEnrichWithPriceFloors(t *testing.T) { 53 rates := map[string]map[string]float64{ 54 "USD": { 55 "INR": 70, 56 "EUR": 0.9, 57 "JPY": 5.09, 58 }, 59 } 60 61 testAccountConfig := config.Account{ 62 PriceFloors: config.AccountPriceFloors{ 63 Enabled: true, 64 UseDynamicData: false, 65 MaxRule: 100, 66 MaxSchemaDims: 5, 67 }, 68 } 69 70 width := int64(300) 71 height := int64(600) 72 73 testCases := []struct { 74 name string 75 bidRequestWrapper *openrtb_ext.RequestWrapper 76 account config.Account 77 conversions currency.Conversions 78 Skipped bool 79 err string 80 expFloorVal float64 81 expFloorCur string 82 expPriceFlrLoc string 83 expSchemaVersion string 84 }{ 85 { 86 name: "Floors disabled in account config", 87 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 88 BidRequest: &openrtb2.BidRequest{ 89 Site: &openrtb2.Site{ 90 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 91 }, 92 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 93 Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website5.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 94 }, 95 }, 96 account: config.Account{ 97 PriceFloors: config.AccountPriceFloors{ 98 Enabled: false, 99 }, 100 }, 101 err: "Floors feature is disabled at account or in the request", 102 }, 103 { 104 name: "Floors disabled in req.ext.prebid.floors.Enabled=false config", 105 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 106 BidRequest: &openrtb2.BidRequest{ 107 Site: &openrtb2.Site{ 108 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 109 }, 110 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 111 Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":false,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 112 }, 113 }, 114 account: testAccountConfig, 115 err: "Floors feature is disabled at account or in the request", 116 }, 117 { 118 name: "Floors enabled in req.ext.prebid.floors.Enabled and enabled account config", 119 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 120 BidRequest: &openrtb2.BidRequest{ 121 Site: &openrtb2.Site{ 122 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 123 }, 124 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 125 Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 2 from req","currency":"USD","values":{"banner|300x250|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}},{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 126 }, 127 }, 128 account: testAccountConfig, 129 expFloorVal: 5, 130 expFloorCur: "USD", 131 expPriceFlrLoc: openrtb_ext.RequestLocation, 132 }, 133 { 134 name: "Skiprate = 100, Floors enabled in req.ext.prebid.floors.Enabled and account config: Floors singalling skipped ", 135 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 136 BidRequest: &openrtb2.BidRequest{ 137 Site: &openrtb2.Site{ 138 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 139 }, 140 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 141 Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"skiprate": 100,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 142 }, 143 }, 144 account: testAccountConfig, 145 Skipped: true, 146 }, 147 { 148 name: "Single ModelGroup, Invalid Skiprate = 110: Floors singalling skipped", 149 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 150 BidRequest: &openrtb2.BidRequest{ 151 Site: &openrtb2.Site{ 152 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 153 }, 154 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 155 Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"skiprate": 110,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 156 }, 157 }, 158 account: testAccountConfig, 159 err: "Invalid SkipRate = '110' at ext.prebid.floors.skiprate", 160 expPriceFlrLoc: openrtb_ext.RequestLocation, 161 }, 162 { 163 name: "Multiple ModelGroups, Invalid Skiprate = 110: in one group, Floors singalling done using second ModelGroup", 164 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 165 BidRequest: &openrtb2.BidRequest{ 166 Site: &openrtb2.Site{ 167 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 168 }, 169 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 170 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":11,"floormincur":"USD","data":{"currency":"USD","floorsschemaversion":"2","modelgroups":[{"modelweight":50,"modelversion":"version2","schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|*|*":11.01,"*|*|www.website1.com":17.01},"default":21},{"modelweight":50,"modelversion":"version11","skiprate":110,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"},"values":{"*|300x250|*":11.01,"*|300x250|www.website1.com":100.01},"default":21}]},"enforcement":{"enforcepbs":true,"floordeals":true},"enabled":true}}}`), 171 }, 172 }, 173 account: testAccountConfig, 174 err: "Invalid Floor Model = 'version11' due to SkipRate = '110' is out of range (1-100)", 175 expFloorVal: 11.01, 176 expFloorCur: "USD", 177 expPriceFlrLoc: openrtb_ext.RequestLocation, 178 expSchemaVersion: "2", 179 }, 180 { 181 name: "Rule selection with Site object, banner|300x600|www.website.com", 182 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 183 BidRequest: &openrtb2.BidRequest{ 184 Site: &openrtb2.Site{ 185 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 186 }, 187 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{W: &width, H: &height}}}, 188 Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"BANNER|300x600|WWW.WEBSITE.COM":5,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 189 }, 190 }, 191 account: testAccountConfig, 192 expFloorVal: 5, 193 expFloorCur: "USD", 194 expPriceFlrLoc: openrtb_ext.RequestLocation, 195 }, 196 { 197 name: "Rule selection with App object, *|*|www.test.com", 198 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 199 BidRequest: &openrtb2.BidRequest{ 200 App: &openrtb2.App{ 201 Domain: "www.test.com", 202 }, 203 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{W: &width, H: &height}}}, 204 Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x600|www.website.com":5,"*|*|www.test.com":15,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 205 }, 206 }, 207 account: testAccountConfig, 208 expFloorVal: 15, 209 expFloorCur: "USD", 210 expPriceFlrLoc: openrtb_ext.RequestLocation, 211 }, 212 { 213 name: "Floors Signalling not done as req.ext.prebid.floors not provided", 214 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 215 BidRequest: &openrtb2.BidRequest{ 216 App: &openrtb2.App{ 217 Domain: "www.test.com", 218 }, 219 Imp: []openrtb2.Imp{{ID: "1234", BidFloor: 10, BidFloorCur: "EUR", Banner: &openrtb2.Banner{W: &width, H: &height}}}, 220 Ext: json.RawMessage(`{"prebid":{}}`), 221 }, 222 }, 223 account: testAccountConfig, 224 expFloorVal: 10, 225 expFloorCur: "EUR", 226 expPriceFlrLoc: openrtb_ext.NoDataLocation, 227 err: "Empty Floors data", 228 }, 229 { 230 name: "BidFloor(USD) Less than MinBidFloor(INR) with different currency", 231 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 232 BidRequest: &openrtb2.BidRequest{ 233 Site: &openrtb2.Site{ 234 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 235 }, 236 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 237 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":80,"floormincur":"INR","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":1,"*|*|www.test.com":15,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 238 }, 239 }, 240 account: testAccountConfig, 241 expFloorVal: 1.1429, 242 expFloorCur: "USD", 243 expPriceFlrLoc: openrtb_ext.RequestLocation, 244 }, 245 { 246 name: "BidFloor(INR) Less than MinBidFloor(USD) with different currency", 247 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 248 BidRequest: &openrtb2.BidRequest{ 249 Site: &openrtb2.Site{ 250 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 251 }, 252 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 253 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"floormincur":"USD","data":{"currency":"INR","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com":60,"*|*|www.test.com":65,"*|*|*":67},"Default":50,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 254 }, 255 }, 256 account: testAccountConfig, 257 expFloorVal: 70, 258 expFloorCur: "INR", 259 expPriceFlrLoc: openrtb_ext.RequestLocation, 260 }, 261 { 262 name: "BidFloor is greater than MinBidFloor with same currency", 263 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 264 BidRequest: &openrtb2.BidRequest{ 265 Site: &openrtb2.Site{ 266 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 267 }, 268 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 269 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":1,"floormincur":"USD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com":2,"*|*|www.test.com":1.5,"*|*|*":1.7},"Default":5,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 270 }, 271 }, 272 account: testAccountConfig, 273 expFloorVal: 2, 274 expFloorCur: "USD", 275 expPriceFlrLoc: openrtb_ext.RequestLocation, 276 }, 277 { 278 name: "BidFloor Less than MinBidFloor with same currency", 279 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 280 BidRequest: &openrtb2.BidRequest{ 281 Site: &openrtb2.Site{ 282 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 283 }, 284 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 285 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":3,"floormincur":"USD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com":2,"*|*|www.test.com":1.5,"*|*|*":1.7},"Default":5,"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 286 }, 287 }, 288 account: testAccountConfig, 289 expFloorVal: 3, 290 expFloorCur: "USD", 291 expPriceFlrLoc: openrtb_ext.RequestLocation, 292 }, 293 { 294 name: "No Rule matching, default value provided", 295 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 296 BidRequest: &openrtb2.BidRequest{ 297 Site: &openrtb2.Site{ 298 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 299 }, 300 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 301 Ext: json.RawMessage(`{"prebid":{"floors":{"data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com1":2,"*|*|www.test2.com":1.5},"schema":{"fields":["mediaType","size","domain"]}, "default": 20}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 302 }, 303 }, 304 account: testAccountConfig, 305 expFloorVal: 20, 306 expFloorCur: "USD", 307 expPriceFlrLoc: openrtb_ext.RequestLocation, 308 }, 309 { 310 name: "No Rule matching, default value less than floorMin", 311 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 312 BidRequest: &openrtb2.BidRequest{ 313 Site: &openrtb2.Site{ 314 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 315 }, 316 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 317 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":15,"floormincur":"USD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com1":2,"*|*|www.test2.com":1.5},"schema":{"fields":["mediaType","size","domain"]}, "default": 5}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 318 }, 319 }, 320 account: testAccountConfig, 321 expFloorVal: 15, 322 expFloorCur: "USD", 323 expPriceFlrLoc: openrtb_ext.RequestLocation, 324 }, 325 { 326 name: "imp.bidfloor provided, No Rule matching, MinBidFloor provided", 327 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 328 BidRequest: &openrtb2.BidRequest{ 329 Site: &openrtb2.Site{ 330 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 331 }, 332 Imp: []openrtb2.Imp{{ID: "1234", BidFloor: 100, BidFloorCur: "INR", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 333 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":2,"floormincur":"USD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","values":{"banner|300x250|www.website.com1":2,"*|*|www.test2.com":1.5},"schema":{"fields":["mediaType","size","domain"]}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 334 }, 335 }, 336 account: testAccountConfig, 337 expFloorVal: 100, 338 expFloorCur: "INR", 339 expPriceFlrLoc: openrtb_ext.RequestLocation, 340 }, 341 { 342 name: "Empty RequestWrapper ", 343 bidRequestWrapper: nil, 344 account: testAccountConfig, 345 err: "Empty bidrequest", 346 }, 347 { 348 name: "Invalid Floor Min Currency", 349 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 350 BidRequest: &openrtb2.BidRequest{ 351 Site: &openrtb2.Site{ 352 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 353 }, 354 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 355 Ext: json.RawMessage(`{"prebid":{"floors":{"floormin":80,"floormincur":"ABCD","data":{"currency":"USD","modelgroups":[{"modelversion":"model 1 from req","currency":"USD","values":{"banner|300x250|www.website.com":1,"*|*|www.test.com":15,"*|*|*":7},"schema":{"fields":["mediaType","size","domain"],"delimiter":"|"}}]},"enabled":true,"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 356 }, 357 }, 358 account: testAccountConfig, 359 err: "Error in getting FloorMin value : 'currency: tag is not well-formed'", 360 expPriceFlrLoc: openrtb_ext.RequestLocation, 361 }, 362 } 363 364 for _, tc := range testCases { 365 t.Run(tc.name, func(t *testing.T) { 366 367 ErrList := EnrichWithPriceFloors(tc.bidRequestWrapper, tc.account, getCurrencyRates(rates)) 368 if tc.bidRequestWrapper != nil { 369 assert.Equal(t, tc.bidRequestWrapper.Imp[0].BidFloor, tc.expFloorVal, tc.name) 370 assert.Equal(t, tc.bidRequestWrapper.Imp[0].BidFloorCur, tc.expFloorCur, tc.name) 371 requestExt, err := tc.bidRequestWrapper.GetRequestExt() 372 if err == nil { 373 if tc.Skipped { 374 assert.Equal(t, *requestExt.GetPrebid().Floors.Skipped, tc.Skipped, tc.name) 375 } else { 376 assert.Equal(t, requestExt.GetPrebid().Floors.PriceFloorLocation, tc.expPriceFlrLoc, tc.name) 377 if tc.expSchemaVersion != "" { 378 assert.Equal(t, requestExt.GetPrebid().Floors.Data.FloorsSchemaVersion, tc.expSchemaVersion, tc.name) 379 } 380 } 381 } 382 } 383 if len(ErrList) > 0 { 384 assert.Equal(t, ErrList[0].Error(), tc.err, tc.name) 385 } 386 }) 387 } 388 } 389 390 func getTrue() *bool { 391 trueFlag := true 392 return &trueFlag 393 } 394 395 func TestResolveFloors(t *testing.T) { 396 rates := map[string]map[string]float64{ 397 "USD": { 398 "INR": 70, 399 "EUR": 0.9, 400 "JPY": 5.09, 401 }, 402 } 403 404 testCases := []struct { 405 name string 406 bidRequestWrapper *openrtb_ext.RequestWrapper 407 account config.Account 408 conversions currency.Conversions 409 expErr []error 410 expFloors *openrtb_ext.PriceFloorRules 411 }{ 412 { 413 name: "Dynamic fetch disabled, only enforcement object present in req.ext", 414 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 415 BidRequest: &openrtb2.BidRequest{ 416 Site: &openrtb2.Site{ 417 Publisher: &openrtb2.Publisher{Domain: "www.website.com"}, 418 }, 419 Imp: []openrtb2.Imp{{ID: "1234", Banner: &openrtb2.Banner{Format: []openrtb2.Format{{W: 300, H: 250}}}}}, 420 Ext: json.RawMessage(`{"prebid":{"floors":{"enforcement":{"enforcepbs":true,"floordeals":true,"enforcerate":100}}}}`), 421 }, 422 }, 423 account: config.Account{ 424 PriceFloors: config.AccountPriceFloors{ 425 Enabled: true, 426 UseDynamicData: false, 427 }, 428 }, 429 expFloors: &openrtb_ext.PriceFloorRules{ 430 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 431 EnforcePBS: getTrue(), 432 EnforceRate: 100, 433 FloorDeals: getTrue(), 434 }, 435 FetchStatus: openrtb_ext.FetchNone, 436 PriceFloorLocation: openrtb_ext.RequestLocation, 437 }, 438 }, 439 } 440 441 for _, tc := range testCases { 442 t.Run(tc.name, func(t *testing.T) { 443 resolvedFloors, _ := resolveFloors(tc.account, tc.bidRequestWrapper, getCurrencyRates(rates)) 444 assert.Equal(t, resolvedFloors, tc.expFloors, tc.name) 445 }) 446 } 447 } 448 449 func printFloors(floors *openrtb_ext.PriceFloorRules) string { 450 fbytes, _ := json.Marshal(floors) 451 return string(fbytes) 452 } 453 454 func TestCreateFloorsFrom(t *testing.T) { 455 456 testAccountConfig := config.Account{ 457 PriceFloors: config.AccountPriceFloors{ 458 Enabled: true, 459 UseDynamicData: false, 460 MaxRule: 100, 461 MaxSchemaDims: 5, 462 }, 463 } 464 465 type args struct { 466 floors *openrtb_ext.PriceFloorRules 467 account config.Account 468 fetchStatus string 469 floorLocation string 470 } 471 testCases := []struct { 472 name string 473 args args 474 want *openrtb_ext.PriceFloorRules 475 want1 []error 476 }{ 477 { 478 name: "floor provider should be selected from floor json", 479 args: args{ 480 account: testAccountConfig, 481 floors: &openrtb_ext.PriceFloorRules{ 482 Enabled: getTrue(), 483 FloorMin: 10.11, 484 FloorMinCur: "EUR", 485 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 486 EnforcePBS: getTrue(), 487 EnforceRate: 100, 488 FloorDeals: getTrue(), 489 }, 490 Data: &openrtb_ext.PriceFloorData{ 491 Currency: "USD", 492 ModelGroups: []openrtb_ext.PriceFloorModelGroup{ 493 { 494 ModelVersion: "model from fetched", 495 Currency: "USD", 496 Values: map[string]float64{ 497 "banner|300x600|www.website5.com": 15, 498 "*|*|*": 25, 499 }, 500 Schema: openrtb_ext.PriceFloorSchema{ 501 Fields: []string{"mediaType", "size", "domain"}, 502 }, 503 }, 504 }, 505 FloorProvider: "PM", 506 }, 507 }, 508 fetchStatus: openrtb_ext.FetchSuccess, 509 floorLocation: openrtb_ext.FetchLocation, 510 }, 511 want: &openrtb_ext.PriceFloorRules{ 512 Enabled: getTrue(), 513 FloorMin: 10.11, 514 FloorMinCur: "EUR", 515 FetchStatus: openrtb_ext.FetchSuccess, 516 PriceFloorLocation: openrtb_ext.FetchLocation, 517 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 518 EnforcePBS: getTrue(), 519 EnforceRate: 100, 520 FloorDeals: getTrue(), 521 }, 522 Data: &openrtb_ext.PriceFloorData{ 523 Currency: "USD", 524 ModelGroups: []openrtb_ext.PriceFloorModelGroup{ 525 { 526 ModelVersion: "model from fetched", 527 Currency: "USD", 528 Values: map[string]float64{ 529 "banner|300x600|www.website5.com": 15, 530 "*|*|*": 25, 531 }, 532 Schema: openrtb_ext.PriceFloorSchema{ 533 Fields: []string{"mediaType", "size", "domain"}, 534 }, 535 }, 536 }, 537 FloorProvider: "PM", 538 }, 539 }, 540 }, 541 { 542 name: "floor provider will be empty if no value provided in floor json", 543 args: args{ 544 account: testAccountConfig, 545 floors: &openrtb_ext.PriceFloorRules{ 546 Enabled: getTrue(), 547 FloorMin: 10.11, 548 FloorMinCur: "EUR", 549 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 550 EnforcePBS: getTrue(), 551 EnforceRate: 100, 552 FloorDeals: getTrue(), 553 }, 554 Data: &openrtb_ext.PriceFloorData{ 555 Currency: "USD", 556 ModelGroups: []openrtb_ext.PriceFloorModelGroup{ 557 { 558 ModelVersion: "model from request", 559 Currency: "USD", 560 Values: map[string]float64{ 561 "banner|300x600|www.website5.com": 15, 562 "*|*|*": 25, 563 }, 564 Schema: openrtb_ext.PriceFloorSchema{ 565 Fields: []string{"mediaType", "size", "domain"}, 566 }, 567 }, 568 }, 569 FloorProvider: "", 570 }, 571 }, 572 fetchStatus: openrtb_ext.FetchSuccess, 573 floorLocation: openrtb_ext.FetchLocation, 574 }, 575 want: &openrtb_ext.PriceFloorRules{ 576 Enabled: getTrue(), 577 FloorMin: 10.11, 578 FloorMinCur: "EUR", 579 FetchStatus: openrtb_ext.FetchSuccess, 580 PriceFloorLocation: openrtb_ext.FetchLocation, 581 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 582 EnforcePBS: getTrue(), 583 EnforceRate: 100, 584 FloorDeals: getTrue(), 585 }, 586 Data: &openrtb_ext.PriceFloorData{ 587 Currency: "USD", 588 ModelGroups: []openrtb_ext.PriceFloorModelGroup{ 589 { 590 ModelVersion: "model from request", 591 Currency: "USD", 592 Values: map[string]float64{ 593 "banner|300x600|www.website5.com": 15, 594 "*|*|*": 25, 595 }, 596 Schema: openrtb_ext.PriceFloorSchema{ 597 Fields: []string{"mediaType", "size", "domain"}, 598 }, 599 }, 600 }, 601 FloorProvider: "", 602 }, 603 }, 604 }, 605 { 606 name: "only floor enforcement object present", 607 args: args{ 608 account: testAccountConfig, 609 floors: &openrtb_ext.PriceFloorRules{ 610 Enabled: getTrue(), 611 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 612 EnforcePBS: getTrue(), 613 EnforceRate: 100, 614 FloorDeals: getTrue(), 615 }, 616 }, 617 fetchStatus: openrtb_ext.FetchNone, 618 floorLocation: openrtb_ext.RequestLocation, 619 }, 620 want: &openrtb_ext.PriceFloorRules{ 621 FetchStatus: openrtb_ext.FetchNone, 622 PriceFloorLocation: openrtb_ext.RequestLocation, 623 Enforcement: &openrtb_ext.PriceFloorEnforcement{ 624 EnforcePBS: getTrue(), 625 EnforceRate: 100, 626 FloorDeals: getTrue(), 627 }, 628 }, 629 }, 630 { 631 name: "Invalid modelGroup with skipRate = 110", 632 args: args{ 633 account: testAccountConfig, 634 floors: &openrtb_ext.PriceFloorRules{ 635 Enabled: getTrue(), 636 Data: &openrtb_ext.PriceFloorData{ 637 Currency: "USD", 638 ModelGroups: []openrtb_ext.PriceFloorModelGroup{ 639 { 640 ModelVersion: "model from fetched", 641 Currency: "USD", 642 SkipRate: 110, 643 Values: map[string]float64{ 644 "banner|300x600|www.website5.com": 15, 645 "*|*|*": 25, 646 }, 647 Schema: openrtb_ext.PriceFloorSchema{ 648 Fields: []string{"mediaType", "size", "domain"}, 649 }, 650 }, 651 }, 652 }, 653 }, 654 fetchStatus: openrtb_ext.FetchNone, 655 floorLocation: openrtb_ext.RequestLocation, 656 }, 657 want: &openrtb_ext.PriceFloorRules{ 658 FetchStatus: openrtb_ext.FetchNone, 659 PriceFloorLocation: openrtb_ext.RequestLocation, 660 }, 661 want1: []error{ 662 errors.New("Invalid Floor Model = 'model from fetched' due to SkipRate = '110' is out of range (1-100)"), 663 }, 664 }, 665 } 666 for _, tc := range testCases { 667 t.Run(tc.name, func(t *testing.T) { 668 got, got1 := createFloorsFrom(tc.args.floors, tc.args.account, tc.args.fetchStatus, tc.args.floorLocation) 669 assert.Equal(t, got1, tc.want1, tc.name) 670 assert.Equal(t, got, tc.want, tc.name) 671 }) 672 } 673 } 674 675 func TestIsPriceFloorsEnabled(t *testing.T) { 676 type args struct { 677 account config.Account 678 bidRequestWrapper *openrtb_ext.RequestWrapper 679 } 680 tests := []struct { 681 name string 682 args args 683 want bool 684 }{ 685 { 686 name: "Disabled in account and req", 687 args: args{ 688 account: config.Account{PriceFloors: config.AccountPriceFloors{Enabled: false}}, 689 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 690 BidRequest: &openrtb2.BidRequest{ 691 Ext: json.RawMessage(`{"prebid":{"floors":{"enabled": false} }}`), 692 }, 693 }, 694 }, 695 want: false, 696 }, 697 { 698 name: "Enabled in account and req", 699 args: args{ 700 account: config.Account{PriceFloors: config.AccountPriceFloors{Enabled: true}}, 701 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 702 BidRequest: &openrtb2.BidRequest{ 703 Ext: json.RawMessage(`{"prebid":{"floors":{"enabled": true} }}`), 704 }, 705 }, 706 }, 707 want: true, 708 }, 709 { 710 name: "disabled in account and enabled req", 711 args: args{ 712 account: config.Account{PriceFloors: config.AccountPriceFloors{Enabled: false}}, 713 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 714 BidRequest: &openrtb2.BidRequest{ 715 Ext: json.RawMessage(`{"prebid":{"floors":{"enabled": true} }}`), 716 }, 717 }, 718 }, 719 want: false, 720 }, 721 { 722 name: "Enabled in account and disabled in req", 723 args: args{ 724 account: config.Account{PriceFloors: config.AccountPriceFloors{Enabled: true}}, 725 bidRequestWrapper: &openrtb_ext.RequestWrapper{ 726 BidRequest: &openrtb2.BidRequest{ 727 Ext: json.RawMessage(`{"prebid":{"floors":{"enabled": false} }}`)}, 728 }, 729 }, 730 want: false, 731 }, 732 } 733 for _, tt := range tests { 734 t.Run(tt.name, func(t *testing.T) { 735 got := isPriceFloorsEnabled(tt.args.account, tt.args.bidRequestWrapper) 736 assert.Equal(t, got, tt.want, tt.name) 737 }) 738 } 739 }