github.com/prebid/prebid-server@v0.275.0/ortb/default_test.go (about) 1 package ortb 2 3 import ( 4 "encoding/json" 5 "testing" 6 7 "github.com/prebid/openrtb/v19/openrtb2" 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 "github.com/prebid/prebid-server/openrtb_ext" 12 "github.com/prebid/prebid-server/util/ptrutil" 13 ) 14 15 func TestSetDefaults(t *testing.T) { 16 secure0 := int8(0) 17 secure1 := int8(1) 18 19 testCases := []struct { 20 name string 21 givenRequest openrtb2.BidRequest 22 expectedRequest openrtb2.BidRequest 23 expectedErr string 24 }{ 25 { 26 name: "empty", 27 givenRequest: openrtb2.BidRequest{}, 28 expectedRequest: openrtb2.BidRequest{}, 29 }, 30 { 31 name: "malformed request.ext", 32 givenRequest: openrtb2.BidRequest{Ext: json.RawMessage(`malformed`)}, 33 expectedRequest: openrtb2.BidRequest{Ext: json.RawMessage(`malformed`)}, 34 expectedErr: "invalid character 'm' looking for beginning of value", 35 }, 36 { 37 name: "targeting", // tests integration with setDefaultsTargeting 38 givenRequest: openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{"targeting":{}}}`)}, 39 expectedRequest: openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":20,"increment":0.1}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true}}}`)}, 40 }, 41 { 42 name: "imp", // tests integration with setDefaultsImp 43 givenRequest: openrtb2.BidRequest{Imp: []openrtb2.Imp{{Secure: &secure0}, {Secure: nil}}}, 44 expectedRequest: openrtb2.BidRequest{Imp: []openrtb2.Imp{{Secure: &secure0}, {Secure: &secure1}}}, 45 }, 46 } 47 48 for _, test := range testCases { 49 t.Run(test.name, func(t *testing.T) { 50 wrapper := &openrtb_ext.RequestWrapper{BidRequest: &test.givenRequest} 51 52 // run 53 err := SetDefaults(wrapper) 54 55 // assert error 56 if len(test.expectedErr) > 0 { 57 assert.EqualError(t, err, test.expectedErr, "Error") 58 } 59 60 // rebuild request 61 require.NoError(t, wrapper.RebuildRequest(), "Rebuild Request") 62 63 // assert 64 if len(test.expectedErr) > 0 { 65 assert.EqualError(t, err, test.expectedErr, "Error") 66 assert.Equal(t, &test.expectedRequest, wrapper.BidRequest, "Request") 67 } else { 68 // assert request as json to ignore order in ext fields 69 expectedRequestJSON, err := json.Marshal(test.expectedRequest) 70 require.NoError(t, err, "Marshal Expected Request") 71 72 actualRequestJSON, err := json.Marshal(wrapper.BidRequest) 73 require.NoError(t, err, "Marshal Actual Request") 74 75 assert.JSONEq(t, string(expectedRequestJSON), string(actualRequestJSON), "Request") 76 } 77 }) 78 } 79 } 80 81 func TestSetDefaultsTargeting(t *testing.T) { 82 defaultGranularity := openrtb_ext.PriceGranularity{ 83 Precision: ptrutil.ToPtr(DefaultPriceGranularityPrecision), 84 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 20, Increment: 0.1}}, 85 } 86 87 testCases := []struct { 88 name string 89 givenTargeting *openrtb_ext.ExtRequestTargeting 90 expectedTargeting *openrtb_ext.ExtRequestTargeting 91 expectedModified bool 92 }{ 93 { 94 name: "nil", 95 givenTargeting: nil, 96 expectedTargeting: nil, 97 }, 98 { 99 name: "empty-targeting", 100 givenTargeting: &openrtb_ext.ExtRequestTargeting{}, 101 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 102 PriceGranularity: &defaultGranularity, 103 IncludeWinners: ptrutil.ToPtr(DefaultTargetingIncludeWinners), 104 IncludeBidderKeys: ptrutil.ToPtr(DefaultTargetingIncludeBidderKeys), 105 }, 106 expectedModified: true, 107 }, 108 { 109 name: "populated-partial", // precision and includewinners defaults set 110 givenTargeting: &openrtb_ext.ExtRequestTargeting{ 111 PriceGranularity: &openrtb_ext.PriceGranularity{ 112 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 113 }, 114 IncludeBidderKeys: ptrutil.ToPtr(false), 115 }, 116 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 117 PriceGranularity: &openrtb_ext.PriceGranularity{ 118 Precision: ptrutil.ToPtr(DefaultPriceGranularityPrecision), 119 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 120 }, 121 IncludeWinners: ptrutil.ToPtr(DefaultTargetingIncludeWinners), 122 IncludeBidderKeys: ptrutil.ToPtr(false), 123 }, 124 expectedModified: true, 125 }, 126 { 127 name: "populated-no-granularity", 128 givenTargeting: &openrtb_ext.ExtRequestTargeting{ 129 PriceGranularity: &openrtb_ext.PriceGranularity{}, 130 IncludeWinners: ptrutil.ToPtr(false), 131 IncludeBidderKeys: ptrutil.ToPtr(false), 132 }, 133 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 134 PriceGranularity: &defaultGranularity, 135 IncludeWinners: ptrutil.ToPtr(false), 136 IncludeBidderKeys: ptrutil.ToPtr(false), 137 }, 138 expectedModified: true, 139 }, 140 { 141 name: "populated-ranges-nil", 142 givenTargeting: &openrtb_ext.ExtRequestTargeting{ 143 PriceGranularity: &openrtb_ext.PriceGranularity{ 144 Precision: ptrutil.ToPtr(4), 145 Ranges: nil, 146 }, 147 }, 148 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 149 PriceGranularity: &defaultGranularity, 150 IncludeWinners: ptrutil.ToPtr(DefaultTargetingIncludeWinners), 151 IncludeBidderKeys: ptrutil.ToPtr(DefaultTargetingIncludeBidderKeys), 152 }, 153 expectedModified: true, 154 }, 155 { 156 name: "populated-ranges-nil-mediatypepricegranularity-video-banner-native", 157 givenTargeting: &openrtb_ext.ExtRequestTargeting{ 158 PriceGranularity: &openrtb_ext.PriceGranularity{ 159 Precision: ptrutil.ToPtr(4), 160 Ranges: nil, 161 }, 162 MediaTypePriceGranularity: openrtb_ext.MediaTypePriceGranularity{ 163 Video: &openrtb_ext.PriceGranularity{ 164 Precision: ptrutil.ToPtr(4), 165 Ranges: nil, 166 }, 167 Banner: &openrtb_ext.PriceGranularity{ 168 Precision: ptrutil.ToPtr(4), 169 Ranges: nil, 170 }, 171 Native: &openrtb_ext.PriceGranularity{ 172 Precision: ptrutil.ToPtr(4), 173 Ranges: nil, 174 }, 175 }, 176 }, 177 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 178 PriceGranularity: &defaultGranularity, 179 MediaTypePriceGranularity: openrtb_ext.MediaTypePriceGranularity{ 180 Video: &defaultGranularity, 181 Banner: &defaultGranularity, 182 Native: &defaultGranularity, 183 }, 184 IncludeWinners: ptrutil.ToPtr(DefaultTargetingIncludeWinners), 185 IncludeBidderKeys: ptrutil.ToPtr(DefaultTargetingIncludeBidderKeys), 186 }, 187 expectedModified: true, 188 }, 189 { 190 name: "populated-ranges-empty", 191 givenTargeting: &openrtb_ext.ExtRequestTargeting{ 192 PriceGranularity: &openrtb_ext.PriceGranularity{ 193 Precision: ptrutil.ToPtr(4), 194 Ranges: []openrtb_ext.GranularityRange{}, 195 }, 196 }, 197 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 198 PriceGranularity: &defaultGranularity, 199 IncludeWinners: ptrutil.ToPtr(DefaultTargetingIncludeWinners), 200 IncludeBidderKeys: ptrutil.ToPtr(DefaultTargetingIncludeBidderKeys), 201 }, 202 expectedModified: true, 203 }, 204 { 205 name: "populated-ranges-empty-mediatypepricegranularity-video-banner-native", 206 givenTargeting: &openrtb_ext.ExtRequestTargeting{ 207 PriceGranularity: &openrtb_ext.PriceGranularity{ 208 Precision: ptrutil.ToPtr(4), 209 Ranges: []openrtb_ext.GranularityRange{}, 210 }, 211 MediaTypePriceGranularity: openrtb_ext.MediaTypePriceGranularity{ 212 Video: &openrtb_ext.PriceGranularity{ 213 Precision: ptrutil.ToPtr(4), 214 Ranges: []openrtb_ext.GranularityRange{}, 215 }, 216 Banner: &openrtb_ext.PriceGranularity{ 217 Precision: ptrutil.ToPtr(4), 218 Ranges: []openrtb_ext.GranularityRange{}, 219 }, 220 Native: &openrtb_ext.PriceGranularity{ 221 Precision: ptrutil.ToPtr(4), 222 Ranges: []openrtb_ext.GranularityRange{}, 223 }, 224 }, 225 }, 226 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 227 PriceGranularity: &defaultGranularity, 228 MediaTypePriceGranularity: openrtb_ext.MediaTypePriceGranularity{ 229 Video: &defaultGranularity, 230 Banner: &defaultGranularity, 231 Native: &defaultGranularity, 232 }, 233 IncludeWinners: ptrutil.ToPtr(DefaultTargetingIncludeWinners), 234 IncludeBidderKeys: ptrutil.ToPtr(DefaultTargetingIncludeBidderKeys), 235 }, 236 expectedModified: true, 237 }, 238 { 239 name: "populated-full", // no defaults set 240 givenTargeting: &openrtb_ext.ExtRequestTargeting{ 241 PriceGranularity: &openrtb_ext.PriceGranularity{ 242 Precision: ptrutil.ToPtr(4), 243 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 244 }, 245 IncludeWinners: ptrutil.ToPtr(false), 246 IncludeBidderKeys: ptrutil.ToPtr(false), 247 }, 248 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 249 PriceGranularity: &openrtb_ext.PriceGranularity{ 250 Precision: ptrutil.ToPtr(4), 251 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 252 }, 253 IncludeWinners: ptrutil.ToPtr(false), 254 IncludeBidderKeys: ptrutil.ToPtr(false), 255 }, 256 expectedModified: false, 257 }, 258 { 259 name: "populated-full-mediatypepricegranularity-video-banner", // no defaults set 260 givenTargeting: &openrtb_ext.ExtRequestTargeting{ 261 PriceGranularity: &openrtb_ext.PriceGranularity{ 262 Precision: ptrutil.ToPtr(4), 263 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 264 }, 265 MediaTypePriceGranularity: openrtb_ext.MediaTypePriceGranularity{ 266 Video: &openrtb_ext.PriceGranularity{ 267 Precision: ptrutil.ToPtr(4), 268 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 269 }, 270 Banner: &openrtb_ext.PriceGranularity{ 271 Precision: ptrutil.ToPtr(4), 272 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 273 }, 274 Native: &openrtb_ext.PriceGranularity{ 275 Precision: ptrutil.ToPtr(4), 276 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 277 }, 278 }, 279 IncludeWinners: ptrutil.ToPtr(false), 280 IncludeBidderKeys: ptrutil.ToPtr(false), 281 }, 282 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 283 PriceGranularity: &openrtb_ext.PriceGranularity{ 284 Precision: ptrutil.ToPtr(4), 285 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 286 }, 287 MediaTypePriceGranularity: openrtb_ext.MediaTypePriceGranularity{ 288 Video: &openrtb_ext.PriceGranularity{ 289 Precision: ptrutil.ToPtr(4), 290 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}}, 291 Banner: &openrtb_ext.PriceGranularity{ 292 Precision: ptrutil.ToPtr(4), 293 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}}, 294 Native: &openrtb_ext.PriceGranularity{ 295 Precision: ptrutil.ToPtr(4), 296 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}}, 297 }, 298 IncludeWinners: ptrutil.ToPtr(false), 299 IncludeBidderKeys: ptrutil.ToPtr(false), 300 }, 301 expectedModified: false, 302 }, 303 { 304 name: "setDefaultsPriceGranularity-integration", 305 givenTargeting: &openrtb_ext.ExtRequestTargeting{ 306 PriceGranularity: &openrtb_ext.PriceGranularity{ 307 Precision: ptrutil.ToPtr(4), 308 Ranges: []openrtb_ext.GranularityRange{{Min: 5, Max: 10, Increment: 1}}, 309 }, 310 IncludeWinners: ptrutil.ToPtr(false), 311 IncludeBidderKeys: ptrutil.ToPtr(false), 312 }, 313 expectedTargeting: &openrtb_ext.ExtRequestTargeting{ 314 PriceGranularity: &openrtb_ext.PriceGranularity{ 315 Precision: ptrutil.ToPtr(4), 316 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 317 }, 318 IncludeWinners: ptrutil.ToPtr(false), 319 IncludeBidderKeys: ptrutil.ToPtr(false), 320 }, 321 expectedModified: true, 322 }, 323 } 324 325 for _, test := range testCases { 326 t.Run(test.name, func(t *testing.T) { 327 actualModified := setDefaultsTargeting(test.givenTargeting) 328 assert.Equal(t, test.expectedModified, actualModified) 329 assert.Equal(t, test.expectedTargeting, test.givenTargeting) 330 }) 331 } 332 } 333 334 func TestSetDefaultsPriceGranularity(t *testing.T) { 335 testCases := []struct { 336 name string 337 givenGranularity *openrtb_ext.PriceGranularity 338 expectedGranularity *openrtb_ext.PriceGranularity 339 expectedModified bool 340 }{ 341 { 342 name: "no-precision", 343 givenGranularity: &openrtb_ext.PriceGranularity{ 344 Precision: nil, 345 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 346 }, 347 expectedGranularity: &openrtb_ext.PriceGranularity{ 348 Precision: ptrutil.ToPtr(2), 349 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 350 }, 351 expectedModified: true, 352 }, 353 { 354 name: "incomplete-range", 355 givenGranularity: &openrtb_ext.PriceGranularity{ 356 Precision: ptrutil.ToPtr(2), 357 Ranges: []openrtb_ext.GranularityRange{{Min: 5, Max: 10, Increment: 1}}, 358 }, 359 expectedGranularity: &openrtb_ext.PriceGranularity{ 360 Precision: ptrutil.ToPtr(2), 361 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 362 }, 363 expectedModified: true, 364 }, 365 { 366 name: "no-precision+incomplete-range", 367 givenGranularity: &openrtb_ext.PriceGranularity{ 368 Precision: nil, 369 Ranges: []openrtb_ext.GranularityRange{{Min: 5, Max: 10, Increment: 1}}, 370 }, 371 expectedGranularity: &openrtb_ext.PriceGranularity{ 372 Precision: ptrutil.ToPtr(2), 373 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 374 }, 375 expectedModified: true, 376 }, 377 { 378 name: "all-set", 379 givenGranularity: &openrtb_ext.PriceGranularity{ 380 Precision: ptrutil.ToPtr(2), 381 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 382 }, 383 expectedGranularity: &openrtb_ext.PriceGranularity{ 384 Precision: ptrutil.ToPtr(2), 385 Ranges: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 386 }, 387 expectedModified: false, 388 }, 389 } 390 391 for _, test := range testCases { 392 t.Run(test.name, func(t *testing.T) { 393 pg, actualModified := setDefaultsPriceGranularity(test.givenGranularity) 394 assert.Equal(t, test.expectedModified, actualModified) 395 assert.Equal(t, test.expectedGranularity, pg) 396 }) 397 } 398 } 399 400 func TestSetDefaultsPriceGranularityRange(t *testing.T) { 401 testCases := []struct { 402 name string 403 givenRange []openrtb_ext.GranularityRange 404 expectedRange []openrtb_ext.GranularityRange 405 expectedModified bool 406 }{ 407 { 408 name: "nil", 409 givenRange: nil, 410 expectedRange: nil, 411 expectedModified: false, 412 }, 413 { 414 name: "empty", 415 givenRange: []openrtb_ext.GranularityRange{}, 416 expectedRange: []openrtb_ext.GranularityRange{}, 417 expectedModified: false, 418 }, 419 { 420 name: "one-ok", 421 givenRange: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 422 expectedRange: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 423 expectedModified: false, 424 }, 425 { 426 name: "one-fixed", 427 givenRange: []openrtb_ext.GranularityRange{{Min: 5, Max: 10, Increment: 1}}, 428 expectedRange: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}}, 429 expectedModified: true, 430 }, 431 { 432 name: "many-ok", 433 givenRange: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}, {Min: 10, Max: 20, Increment: 1}}, 434 expectedRange: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}, {Min: 10, Max: 20, Increment: 1}}, 435 expectedModified: false, 436 }, 437 { 438 name: "many-fixed", 439 givenRange: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}, {Min: 15, Max: 20, Increment: 1}}, 440 expectedRange: []openrtb_ext.GranularityRange{{Min: 0, Max: 10, Increment: 1}, {Min: 10, Max: 20, Increment: 1}}, 441 expectedModified: true, 442 }, 443 } 444 445 for _, test := range testCases { 446 t.Run(test.name, func(t *testing.T) { 447 actualModified := setDefaultsPriceGranularityRange(test.givenRange) 448 assert.Equal(t, test.expectedModified, actualModified) 449 assert.Equal(t, test.expectedRange, test.givenRange) 450 }) 451 } 452 } 453 454 func TestSetDefaultsImp(t *testing.T) { 455 secure0 := int8(0) 456 secure1 := int8(1) 457 458 testCases := []struct { 459 name string 460 givenImps []*openrtb_ext.ImpWrapper 461 expectedImps []*openrtb_ext.ImpWrapper 462 expectedModified bool 463 }{ 464 { 465 name: "nil", 466 givenImps: nil, 467 expectedImps: nil, 468 expectedModified: false, 469 }, 470 { 471 name: "empty", 472 givenImps: []*openrtb_ext.ImpWrapper{}, 473 expectedImps: []*openrtb_ext.ImpWrapper{}, 474 expectedModified: false, 475 }, 476 { 477 name: "one-nil", 478 givenImps: []*openrtb_ext.ImpWrapper{nil}, 479 expectedImps: []*openrtb_ext.ImpWrapper{nil}, 480 expectedModified: false, 481 }, 482 { 483 name: "one-imp-nil", 484 givenImps: []*openrtb_ext.ImpWrapper{{Imp: nil}}, 485 expectedImps: []*openrtb_ext.ImpWrapper{{Imp: nil}}, 486 expectedModified: false, 487 }, 488 { 489 name: "one-imp-secure-0", 490 givenImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: &secure0}}}, 491 expectedImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: &secure0}}}, 492 expectedModified: false, 493 }, 494 { 495 name: "one-imp-secure-1", 496 givenImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: &secure1}}}, 497 expectedImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: &secure1}}}, 498 expectedModified: false, 499 }, 500 { 501 name: "one-imp-secure-nil", 502 givenImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: nil}}}, 503 expectedImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: &secure1}}}, 504 expectedModified: true, 505 }, 506 { 507 name: "one-imp-many-notmodified", 508 givenImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: &secure0}}, {Imp: &openrtb2.Imp{Secure: &secure1}}}, 509 expectedImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: &secure0}}, {Imp: &openrtb2.Imp{Secure: &secure1}}}, 510 expectedModified: false, 511 }, 512 { 513 name: "one-imp-many-modified", 514 givenImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: &secure0}}, {Imp: &openrtb2.Imp{Secure: nil}}}, 515 expectedImps: []*openrtb_ext.ImpWrapper{{Imp: &openrtb2.Imp{Secure: &secure0}}, {Imp: &openrtb2.Imp{Secure: &secure1}}}, 516 expectedModified: true, 517 }, 518 } 519 520 for _, test := range testCases { 521 t.Run(test.name, func(t *testing.T) { 522 actualModified := setDefaultsImp(test.givenImps) 523 assert.Equal(t, test.expectedModified, actualModified) 524 assert.ElementsMatch(t, test.expectedImps, test.givenImps) 525 }) 526 } 527 }