github.com/prebid/prebid-server@v0.275.0/bidadjustment/build_rules_test.go (about) 1 package bidadjustment 2 3 import ( 4 "testing" 5 6 "github.com/prebid/openrtb/v19/openrtb2" 7 "github.com/prebid/prebid-server/config" 8 "github.com/prebid/prebid-server/openrtb_ext" 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestBuildRules(t *testing.T) { 13 testCases := []struct { 14 name string 15 givenBidAdjustments *openrtb_ext.ExtRequestPrebidBidAdjustments 16 expectedRules map[string][]openrtb_ext.Adjustment 17 }{ 18 { 19 name: "OneAdjustment", 20 givenBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 21 MediaType: openrtb_ext.MediaType{ 22 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 23 "bidderA": { 24 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}, 25 }, 26 }, 27 }, 28 }, 29 expectedRules: map[string][]openrtb_ext.Adjustment{ 30 "banner|bidderA|dealId": { 31 { 32 Type: AdjustmentTypeMultiplier, 33 Value: 1.1, 34 }, 35 }, 36 }, 37 }, 38 { 39 name: "MultipleAdjustments", 40 givenBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 41 MediaType: openrtb_ext.MediaType{ 42 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 43 "bidderA": { 44 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}, 45 }, 46 "*": { 47 "diffDealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 1.1, Currency: "USD"}}, 48 "*": []openrtb_ext.Adjustment{{Type: AdjustmentTypeStatic, Value: 5.0, Currency: "USD"}}, 49 }, 50 }, 51 VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 52 "*": { 53 "*": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}, {Type: AdjustmentTypeCPM, Value: 0.18, Currency: "USD"}}, 54 }, 55 }, 56 VideoOutstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 57 "bidderB": { 58 "*": []openrtb_ext.Adjustment{{Type: AdjustmentTypeStatic, Value: 0.25, Currency: "USD"}}, 59 }, 60 }, 61 }, 62 }, 63 expectedRules: map[string][]openrtb_ext.Adjustment{ 64 "banner|bidderA|dealId": { 65 { 66 Type: AdjustmentTypeMultiplier, 67 Value: 1.1, 68 }, 69 }, 70 "banner|*|diffDealId": { 71 { 72 Type: AdjustmentTypeCPM, 73 Value: 1.1, 74 Currency: "USD", 75 }, 76 }, 77 "banner|*|*": { 78 { 79 Type: AdjustmentTypeStatic, 80 Value: 5.0, 81 Currency: "USD", 82 }, 83 }, 84 "video-instream|*|*": { 85 { 86 Type: AdjustmentTypeMultiplier, 87 Value: 1.1, 88 }, 89 { 90 Type: AdjustmentTypeCPM, 91 Value: 0.18, 92 Currency: "USD", 93 }, 94 }, 95 "video-outstream|bidderB|*": { 96 { 97 Type: AdjustmentTypeStatic, 98 Value: 0.25, 99 Currency: "USD", 100 }, 101 }, 102 }, 103 }, 104 { 105 name: "NilAdjustments", 106 givenBidAdjustments: nil, 107 expectedRules: nil, 108 }, 109 } 110 111 for _, test := range testCases { 112 t.Run(test.name, func(t *testing.T) { 113 rules := BuildRules(test.givenBidAdjustments) 114 assert.Equal(t, test.expectedRules, rules) 115 }) 116 } 117 } 118 119 func TestMergeAndValidate(t *testing.T) { 120 testCases := []struct { 121 name string 122 givenRequestWrapper *openrtb_ext.RequestWrapper 123 givenAccount *config.Account 124 expectError bool 125 expectedBidAdjustments *openrtb_ext.ExtRequestPrebidBidAdjustments 126 }{ 127 { 128 name: "ValidReqAndAcctAdjustments", 129 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 130 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)}, 131 }, 132 givenAccount: &config.Account{ 133 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 134 MediaType: openrtb_ext.MediaType{ 135 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 136 "bidderB": { 137 "dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: 1.5}}, 138 }, 139 }, 140 }, 141 }, 142 }, 143 expectError: false, 144 expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 145 MediaType: openrtb_ext.MediaType{ 146 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 147 "bidderA": { 148 "dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: 1.1}}, 149 }, 150 "bidderB": { 151 "dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: 1.5}}, 152 }, 153 }, 154 }, 155 }, 156 }, 157 { 158 name: "InvalidReqAdjustment", 159 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 160 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 200}]}}}}}}`)}, 161 }, 162 givenAccount: &config.Account{ 163 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 164 MediaType: openrtb_ext.MediaType{ 165 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 166 "bidderB": { 167 "dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: 1.5}}, 168 }, 169 }, 170 }, 171 }, 172 }, 173 expectError: true, 174 expectedBidAdjustments: nil, 175 }, 176 { 177 name: "InvalidAcctAdjustment", 178 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 179 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)}, 180 }, 181 givenAccount: &config.Account{ 182 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 183 MediaType: openrtb_ext.MediaType{ 184 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 185 "bidderB": { 186 "dealId": []openrtb_ext.Adjustment{{Type: "multiplier", Value: -1.5}}, 187 }, 188 }, 189 }, 190 }, 191 }, 192 expectError: true, 193 expectedBidAdjustments: nil, 194 }, 195 { 196 name: "InvalidJSON", 197 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 198 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{}}`)}, 199 }, 200 givenAccount: &config.Account{}, 201 expectError: true, 202 expectedBidAdjustments: nil, 203 }, 204 } 205 206 for _, test := range testCases { 207 t.Run(test.name, func(t *testing.T) { 208 mergedBidAdj, err := Merge(test.givenRequestWrapper, test.givenAccount.BidAdjustments) 209 if !test.expectError { 210 assert.NoError(t, err) 211 } else { 212 assert.Error(t, err) 213 } 214 assert.Equal(t, test.expectedBidAdjustments, mergedBidAdj) 215 }) 216 } 217 } 218 219 func TestMerge(t *testing.T) { 220 testCases := []struct { 221 name string 222 givenRequestWrapper *openrtb_ext.RequestWrapper 223 givenAccount *config.Account 224 expectedBidAdjustments *openrtb_ext.ExtRequestPrebidBidAdjustments 225 }{ 226 { 227 name: "DiffBidderNames", 228 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 229 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)}, 230 }, 231 givenAccount: &config.Account{ 232 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 233 MediaType: openrtb_ext.MediaType{ 234 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 235 "bidderB": { 236 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 237 }, 238 }, 239 }, 240 }, 241 }, 242 expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 243 MediaType: openrtb_ext.MediaType{ 244 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 245 "bidderA": { 246 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}, 247 }, 248 "bidderB": { 249 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 250 }, 251 }, 252 }, 253 }, 254 }, 255 { 256 name: "RequestTakesPrecedence", 257 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 258 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"audio":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)}, 259 }, 260 givenAccount: &config.Account{ 261 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 262 MediaType: openrtb_ext.MediaType{ 263 Audio: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 264 "bidderA": { 265 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 266 }, 267 }, 268 }, 269 }, 270 }, 271 expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 272 MediaType: openrtb_ext.MediaType{ 273 Audio: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 274 "bidderA": { 275 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}, 276 }, 277 }, 278 }, 279 }, 280 }, 281 { 282 name: "DiffDealIds", 283 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 284 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"video-instream":{"bidderA":{"dealId":[{ "adjtype": "static", "value": 3.00, "currency": "USD"}]}}}}}}`)}, 285 }, 286 givenAccount: &config.Account{ 287 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 288 MediaType: openrtb_ext.MediaType{ 289 VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 290 "bidderA": { 291 "diffDealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 292 }, 293 }, 294 }, 295 }, 296 }, 297 expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 298 MediaType: openrtb_ext.MediaType{ 299 VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 300 "bidderA": { 301 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeStatic, Value: 3.00, Currency: "USD"}}, 302 "diffDealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 303 }, 304 }, 305 }, 306 }, 307 }, 308 { 309 name: "DiffBidderNamesCpm", 310 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 311 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"native":{"bidderA":{"dealId":[{"adjtype": "cpm", "value": 0.18, "currency": "USD"}]}}}}}}`)}, 312 }, 313 givenAccount: &config.Account{ 314 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 315 MediaType: openrtb_ext.MediaType{ 316 Native: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 317 "bidderB": { 318 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 319 }, 320 }, 321 }, 322 }, 323 }, 324 expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 325 MediaType: openrtb_ext.MediaType{ 326 Native: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 327 "bidderA": { 328 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeCPM, Value: 0.18, Currency: "USD"}}, 329 }, 330 "bidderB": { 331 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 332 }, 333 }, 334 }, 335 }, 336 }, 337 { 338 name: "ReqAdjVideoAcctAdjBanner", 339 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 340 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"video-outstream":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)}, 341 }, 342 givenAccount: &config.Account{ 343 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 344 MediaType: openrtb_ext.MediaType{ 345 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 346 "bidderB": { 347 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 348 }, 349 }, 350 }, 351 }, 352 }, 353 expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 354 MediaType: openrtb_ext.MediaType{ 355 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 356 "bidderB": { 357 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 358 }, 359 }, 360 VideoOutstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 361 "bidderA": { 362 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}, 363 }, 364 }, 365 }, 366 }, 367 }, 368 { 369 name: "RequestNilPrebid", 370 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 371 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"ext":{"bidder": {}}}`)}, 372 }, 373 givenAccount: &config.Account{ 374 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 375 MediaType: openrtb_ext.MediaType{ 376 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 377 "bidderB": { 378 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 379 }, 380 }, 381 }, 382 }, 383 }, 384 expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 385 MediaType: openrtb_ext.MediaType{ 386 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 387 "bidderB": { 388 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 389 }, 390 }, 391 }, 392 }, 393 }, 394 { 395 name: "AcctWildCardRequestVideo", 396 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 397 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"video-instream":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)}, 398 }, 399 givenAccount: &config.Account{ 400 BidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 401 MediaType: openrtb_ext.MediaType{ 402 WildCard: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 403 "bidderB": { 404 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 405 }, 406 }, 407 }, 408 }, 409 }, 410 expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 411 MediaType: openrtb_ext.MediaType{ 412 WildCard: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 413 "bidderB": { 414 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.5}}, 415 }, 416 }, 417 VideoInstream: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 418 "bidderA": { 419 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}, 420 }, 421 }, 422 }, 423 }, 424 }, 425 { 426 name: "NilReqExtPrebidAndAcctBidAdj", 427 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 428 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"ext":{"bidder": {}}}`)}, 429 }, 430 givenAccount: &config.Account{}, 431 expectedBidAdjustments: nil, 432 }, 433 { 434 name: "NilAcctBidAdj", 435 givenRequestWrapper: &openrtb_ext.RequestWrapper{ 436 BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"bidadjustments":{"mediatype":{"banner":{"bidderA":{"dealId":[{ "adjtype": "multiplier", "value": 1.1}]}}}}}}`)}, 437 }, 438 givenAccount: &config.Account{}, 439 expectedBidAdjustments: &openrtb_ext.ExtRequestPrebidBidAdjustments{ 440 MediaType: openrtb_ext.MediaType{ 441 Banner: map[openrtb_ext.BidderName]openrtb_ext.AdjustmentsByDealID{ 442 "bidderA": { 443 "dealId": []openrtb_ext.Adjustment{{Type: AdjustmentTypeMultiplier, Value: 1.1}}, 444 }, 445 }, 446 }, 447 }, 448 }, 449 } 450 451 for _, test := range testCases { 452 t.Run(test.name, func(t *testing.T) { 453 mergedBidAdj, err := merge(test.givenRequestWrapper, test.givenAccount.BidAdjustments) 454 assert.NoError(t, err) 455 assert.Equal(t, test.expectedBidAdjustments, mergedBidAdj) 456 }) 457 } 458 }