github.com/prebid/prebid-server/v2@v2.18.0/analytics/build/build_test.go (about) 1 package build 2 3 import ( 4 "github.com/prebid/prebid-server/v2/openrtb_ext" 5 "github.com/prebid/prebid-server/v2/util/iputil" 6 7 "net/http" 8 "os" 9 "testing" 10 11 "github.com/prebid/openrtb/v20/openrtb2" 12 "github.com/prebid/prebid-server/v2/analytics" 13 "github.com/prebid/prebid-server/v2/config" 14 "github.com/prebid/prebid-server/v2/privacy" 15 "github.com/prebid/prebid-server/v2/util/ptrutil" 16 "github.com/stretchr/testify/assert" 17 ) 18 19 const TEST_DIR string = "testFiles" 20 21 func TestSampleModule(t *testing.T) { 22 var count int 23 am := initAnalytics(&count) 24 am.LogAuctionObject(&analytics.AuctionObject{ 25 Status: http.StatusOK, 26 RequestWrapper: &openrtb_ext.RequestWrapper{BidRequest: getDefaultBidRequest()}, 27 Errors: nil, 28 Response: &openrtb2.BidResponse{}, 29 }, privacy.ActivityControl{}) 30 if count != 1 { 31 t.Errorf("PBSAnalyticsModule failed at LogAuctionObject") 32 } 33 34 am.LogSetUIDObject(&analytics.SetUIDObject{ 35 Status: http.StatusOK, 36 Bidder: "bidders string", 37 UID: "uid", 38 Errors: nil, 39 Success: true, 40 }) 41 if count != 2 { 42 t.Errorf("PBSAnalyticsModule failed at LogSetUIDObject") 43 } 44 45 am.LogCookieSyncObject(&analytics.CookieSyncObject{}) 46 if count != 3 { 47 t.Errorf("PBSAnalyticsModule failed at LogCookieSyncObject") 48 } 49 50 am.LogAmpObject(&analytics.AmpObject{RequestWrapper: &openrtb_ext.RequestWrapper{}}, privacy.ActivityControl{}) 51 if count != 4 { 52 t.Errorf("PBSAnalyticsModule failed at LogAmpObject") 53 } 54 55 am.LogVideoObject(&analytics.VideoObject{RequestWrapper: &openrtb_ext.RequestWrapper{}}, privacy.ActivityControl{}) 56 if count != 5 { 57 t.Errorf("PBSAnalyticsModule failed at LogVideoObject") 58 } 59 60 am.LogNotificationEventObject(&analytics.NotificationEvent{}, privacy.ActivityControl{}) 61 if count != 6 { 62 t.Errorf("PBSAnalyticsModule failed at LogNotificationEventObject") 63 } 64 } 65 66 type sampleModule struct { 67 count *int 68 } 69 70 func (m *sampleModule) LogAuctionObject(ao *analytics.AuctionObject) { *m.count++ } 71 72 func (m *sampleModule) LogVideoObject(vo *analytics.VideoObject) { *m.count++ } 73 74 func (m *sampleModule) LogCookieSyncObject(cso *analytics.CookieSyncObject) { *m.count++ } 75 76 func (m *sampleModule) LogSetUIDObject(so *analytics.SetUIDObject) { *m.count++ } 77 78 func (m *sampleModule) LogAmpObject(ao *analytics.AmpObject) { *m.count++ } 79 80 func (m *sampleModule) LogNotificationEventObject(ne *analytics.NotificationEvent) { *m.count++ } 81 82 func initAnalytics(count *int) analytics.Runner { 83 modules := make(enabledAnalytics, 0) 84 modules["sampleModule"] = &sampleModule{count} 85 return &modules 86 } 87 88 func TestNewPBSAnalytics(t *testing.T) { 89 pbsAnalytics := New(&config.Analytics{}) 90 instance := pbsAnalytics.(enabledAnalytics) 91 92 assert.Equal(t, len(instance), 0) 93 } 94 95 func TestNewPBSAnalytics_FileLogger(t *testing.T) { 96 if _, err := os.Stat(TEST_DIR); os.IsNotExist(err) { 97 if err = os.MkdirAll(TEST_DIR, 0755); err != nil { 98 t.Fatalf("Could not create test directory for FileLogger") 99 } 100 } 101 defer os.RemoveAll(TEST_DIR) 102 mod := New(&config.Analytics{File: config.FileLogs{Filename: TEST_DIR + "/test"}}) 103 switch modType := mod.(type) { 104 case enabledAnalytics: 105 if len(enabledAnalytics(modType)) != 1 { 106 t.Fatalf("Failed to add analytics module") 107 } 108 default: 109 t.Fatalf("Failed to initialize analytics module") 110 } 111 112 pbsAnalytics := New(&config.Analytics{File: config.FileLogs{Filename: TEST_DIR + "/test"}}) 113 instance := pbsAnalytics.(enabledAnalytics) 114 115 assert.Equal(t, len(instance), 1) 116 } 117 118 func TestNewPBSAnalytics_Pubstack(t *testing.T) { 119 pbsAnalyticsWithoutError := New(&config.Analytics{ 120 Pubstack: config.Pubstack{ 121 Enabled: true, 122 ScopeId: "scopeId", 123 IntakeUrl: "https://pubstack.io/intake", 124 Buffers: config.PubstackBuffer{ 125 BufferSize: "100KB", 126 EventCount: 0, 127 Timeout: "30s", 128 }, 129 ConfRefresh: "2h", 130 }, 131 }) 132 instanceWithoutError := pbsAnalyticsWithoutError.(enabledAnalytics) 133 134 assert.Equal(t, len(instanceWithoutError), 1) 135 136 pbsAnalyticsWithError := New(&config.Analytics{ 137 Pubstack: config.Pubstack{ 138 Enabled: true, 139 }, 140 }) 141 instanceWithError := pbsAnalyticsWithError.(enabledAnalytics) 142 assert.Equal(t, len(instanceWithError), 0) 143 } 144 145 func TestNewModuleHttp(t *testing.T) { 146 agmaAnalyticsWithoutError := New(&config.Analytics{ 147 Agma: config.AgmaAnalytics{ 148 Enabled: true, 149 Endpoint: config.AgmaAnalyticsHttpEndpoint{ 150 Url: "http://localhost:8080", 151 Timeout: "1s", 152 }, 153 Buffers: config.AgmaAnalyticsBuffer{ 154 BufferSize: "100KB", 155 EventCount: 50, 156 Timeout: "30s", 157 }, 158 Accounts: []config.AgmaAnalyticsAccount{ 159 { 160 PublisherId: "123", 161 Code: "abc", 162 }, 163 }, 164 }, 165 }) 166 instanceWithoutError := agmaAnalyticsWithoutError.(enabledAnalytics) 167 168 assert.Equal(t, len(instanceWithoutError), 1) 169 170 agmaAnalyticsWithError := New(&config.Analytics{ 171 Agma: config.AgmaAnalytics{ 172 Enabled: true, 173 }, 174 }) 175 instanceWithError := agmaAnalyticsWithError.(enabledAnalytics) 176 assert.Equal(t, len(instanceWithError), 0) 177 } 178 179 func TestSampleModuleActivitiesAllowed(t *testing.T) { 180 var count int 181 am := initAnalytics(&count) 182 183 acAllowed := privacy.NewActivityControl(getActivityConfig("sampleModule", true, true, true)) 184 185 ao := &analytics.AuctionObject{ 186 Status: http.StatusOK, 187 RequestWrapper: &openrtb_ext.RequestWrapper{}, 188 Errors: nil, 189 Response: &openrtb2.BidResponse{}, 190 } 191 192 am.LogAuctionObject(ao, acAllowed) 193 if count != 1 { 194 t.Errorf("PBSAnalyticsModule failed at LogAuctionObject") 195 } 196 197 am.LogAmpObject(&analytics.AmpObject{RequestWrapper: &openrtb_ext.RequestWrapper{}}, acAllowed) 198 if count != 2 { 199 t.Errorf("PBSAnalyticsModule failed at LogAmpObject") 200 } 201 202 am.LogVideoObject(&analytics.VideoObject{RequestWrapper: &openrtb_ext.RequestWrapper{}}, acAllowed) 203 if count != 3 { 204 t.Errorf("PBSAnalyticsModule failed at LogVideoObject") 205 } 206 207 am.LogNotificationEventObject(&analytics.NotificationEvent{}, acAllowed) 208 if count != 4 { 209 t.Errorf("PBSAnalyticsModule failed at LogNotificationEventObject") 210 } 211 } 212 213 func TestSampleModuleActivitiesAllowedAndDenied(t *testing.T) { 214 var count int 215 am := initAnalytics(&count) 216 217 acAllowed := privacy.NewActivityControl(getActivityConfig("sampleModule", true, false, true)) 218 219 rw := &openrtb_ext.RequestWrapper{BidRequest: getDefaultBidRequest()} 220 ao := &analytics.AuctionObject{ 221 RequestWrapper: rw, 222 Status: http.StatusOK, 223 Errors: nil, 224 Response: &openrtb2.BidResponse{}, 225 } 226 227 am.LogAuctionObject(ao, acAllowed) 228 if count != 1 { 229 t.Errorf("PBSAnalyticsModule failed at LogAuctionObject") 230 } 231 232 am.LogAmpObject(&analytics.AmpObject{RequestWrapper: rw}, acAllowed) 233 if count != 2 { 234 t.Errorf("PBSAnalyticsModule failed at LogAmpObject") 235 } 236 237 am.LogVideoObject(&analytics.VideoObject{RequestWrapper: rw}, acAllowed) 238 if count != 3 { 239 t.Errorf("PBSAnalyticsModule failed at LogVideoObject") 240 } 241 242 am.LogNotificationEventObject(&analytics.NotificationEvent{}, acAllowed) 243 if count != 4 { 244 t.Errorf("PBSAnalyticsModule failed at LogNotificationEventObject") 245 } 246 } 247 248 func TestSampleModuleActivitiesDenied(t *testing.T) { 249 var count int 250 am := initAnalytics(&count) 251 252 acDenied := privacy.NewActivityControl(getActivityConfig("sampleModule", false, true, true)) 253 254 ao := &analytics.AuctionObject{ 255 Status: http.StatusOK, 256 Errors: nil, 257 Response: &openrtb2.BidResponse{}, 258 } 259 260 am.LogAuctionObject(ao, acDenied) 261 if count != 0 { 262 t.Errorf("PBSAnalyticsModule failed at LogAuctionObject") 263 } 264 265 am.LogAmpObject(&analytics.AmpObject{}, acDenied) 266 if count != 0 { 267 t.Errorf("PBSAnalyticsModule failed at LogAmpObject") 268 } 269 270 am.LogVideoObject(&analytics.VideoObject{}, acDenied) 271 if count != 0 { 272 t.Errorf("PBSAnalyticsModule failed at LogVideoObject") 273 } 274 275 am.LogNotificationEventObject(&analytics.NotificationEvent{}, acDenied) 276 if count != 0 { 277 t.Errorf("PBSAnalyticsModule failed at LogNotificationEventObject") 278 } 279 } 280 281 func TestEvaluateActivities(t *testing.T) { 282 testCases := []struct { 283 description string 284 givenActivityControl privacy.ActivityControl 285 expectedRequest *openrtb_ext.RequestWrapper 286 expectedAllowActivities bool 287 }{ 288 { 289 description: "all blocked", 290 givenActivityControl: privacy.NewActivityControl(getActivityConfig("sampleModule", false, false, false)), 291 expectedRequest: nil, 292 expectedAllowActivities: false, 293 }, 294 { 295 description: "all allowed", 296 givenActivityControl: privacy.NewActivityControl(getActivityConfig("sampleModule", true, true, true)), 297 expectedRequest: nil, 298 expectedAllowActivities: true, 299 }, 300 301 { 302 description: "ActivityTransmitUserFPD and ActivityTransmitPreciseGeo disabled", 303 givenActivityControl: privacy.NewActivityControl(getActivityConfig("sampleModule", true, false, false)), 304 expectedRequest: &openrtb_ext.RequestWrapper{ 305 BidRequest: &openrtb2.BidRequest{ID: "test_request", User: &openrtb2.User{ID: ""}, Device: &openrtb2.Device{IFA: "", IP: "127.0.0.0"}}, 306 }, 307 expectedAllowActivities: true, 308 }, 309 { 310 description: "ActivityTransmitUserFPD enabled, ActivityTransmitPreciseGeo disabled", 311 givenActivityControl: privacy.NewActivityControl(getActivityConfig("sampleModule", true, true, false)), 312 expectedRequest: &openrtb_ext.RequestWrapper{ 313 BidRequest: &openrtb2.BidRequest{ID: "test_request", User: &openrtb2.User{ID: "user-id"}, Device: &openrtb2.Device{IFA: "device-ifa", IP: "127.0.0.0"}}, 314 }, 315 expectedAllowActivities: true, 316 }, 317 } 318 319 for _, test := range testCases { 320 t.Run(test.description, func(t *testing.T) { 321 rw := &openrtb_ext.RequestWrapper{BidRequest: getDefaultBidRequest()} 322 resActivityAllowed, resRequest := evaluateActivities(rw, test.givenActivityControl, "sampleModule") 323 assert.Equal(t, test.expectedAllowActivities, resActivityAllowed) 324 if test.expectedRequest != nil { 325 assert.Equal(t, test.expectedRequest.User.ID, resRequest.User.ID) 326 assert.Equal(t, test.expectedRequest.Device.IFA, resRequest.Device.IFA) 327 assert.Equal(t, test.expectedRequest.Device.IP, resRequest.Device.IP) 328 } else { 329 assert.Nil(t, resRequest) 330 } 331 332 }) 333 } 334 335 } 336 337 func getDefaultBidRequest() *openrtb2.BidRequest { 338 return &openrtb2.BidRequest{ 339 ID: "test_request", 340 User: &openrtb2.User{ID: "user-id"}, 341 Device: &openrtb2.Device{IFA: "device-ifa", IP: "127.0.0.1"}, 342 } 343 } 344 345 func getActivityConfig(componentName string, allowReportAnalytics, allowTransmitUserFPD, allowTransmitPreciseGeo bool) *config.AccountPrivacy { 346 return &config.AccountPrivacy{ 347 AllowActivities: &config.AllowActivities{ 348 ReportAnalytics: config.Activity{ 349 Default: ptrutil.ToPtr(true), 350 Rules: []config.ActivityRule{ 351 { 352 Allow: allowReportAnalytics, 353 Condition: config.ActivityCondition{ 354 ComponentName: []string{componentName}, 355 ComponentType: []string{"analytics"}, 356 }, 357 }, 358 }, 359 }, 360 TransmitUserFPD: config.Activity{ 361 Default: ptrutil.ToPtr(true), 362 Rules: []config.ActivityRule{ 363 { 364 Allow: allowTransmitUserFPD, 365 Condition: config.ActivityCondition{ 366 ComponentName: []string{componentName}, 367 ComponentType: []string{"analytics"}, 368 }, 369 }, 370 }, 371 }, 372 TransmitPreciseGeo: config.Activity{ 373 Default: ptrutil.ToPtr(true), 374 Rules: []config.ActivityRule{ 375 { 376 Allow: allowTransmitPreciseGeo, 377 Condition: config.ActivityCondition{ 378 ComponentName: []string{componentName}, 379 ComponentType: []string{"analytics"}, 380 }, 381 }, 382 }, 383 }, 384 }, 385 IPv4Config: config.IPv4{ 386 AnonKeepBits: iputil.IPv4DefaultMaskingBitSize, 387 }, 388 IPv6Config: config.IPv6{ 389 AnonKeepBits: iputil.IPv6DefaultMaskingBitSize, 390 }, 391 } 392 } 393 394 type mockAnalytics struct { 395 lastLoggedAuctionBidRequest *openrtb2.BidRequest 396 lastLoggedAmpBidRequest *openrtb2.BidRequest 397 lastLoggedVideoBidRequest *openrtb2.BidRequest 398 } 399 400 func (m *mockAnalytics) LogAuctionObject(ao *analytics.AuctionObject) { 401 m.lastLoggedAuctionBidRequest = ao.RequestWrapper.BidRequest 402 } 403 404 func (m *mockAnalytics) LogAmpObject(ao *analytics.AmpObject) { 405 m.lastLoggedAmpBidRequest = ao.RequestWrapper.BidRequest 406 } 407 408 func (m *mockAnalytics) LogVideoObject(vo *analytics.VideoObject) { 409 m.lastLoggedVideoBidRequest = vo.RequestWrapper.BidRequest 410 } 411 412 func (m *mockAnalytics) LogCookieSyncObject(ao *analytics.CookieSyncObject) {} 413 414 func (m *mockAnalytics) LogSetUIDObject(ao *analytics.SetUIDObject) {} 415 416 func (m *mockAnalytics) LogNotificationEventObject(ao *analytics.NotificationEvent) {} 417 418 func TestLogObject(t *testing.T) { 419 tests := []struct { 420 description string 421 givenRequestWrapper *openrtb_ext.RequestWrapper 422 givenEnabledAnalytics enabledAnalytics 423 givenActivityControl bool 424 givenAuctionObject *analytics.AuctionObject 425 givenAmpObject *analytics.AmpObject 426 givenVideoObject *analytics.VideoObject 427 expectedBidRequest1 *openrtb2.BidRequest 428 expectedBidRequest2 *openrtb2.BidRequest 429 }{ 430 { 431 description: "Multiple analytics modules, clone from evaluate activities, should expect both to have their information to be logged only -- auction", 432 givenEnabledAnalytics: enabledAnalytics{"adapter1": &mockAnalytics{}, "adapter2": &mockAnalytics{}}, 433 givenActivityControl: true, 434 givenAuctionObject: &analytics.AuctionObject{ 435 Status: http.StatusOK, 436 Errors: nil, 437 Response: &openrtb2.BidResponse{}, 438 RequestWrapper: &openrtb_ext.RequestWrapper{ 439 BidRequest: &openrtb2.BidRequest{ 440 ID: "test_request", 441 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true},"adapter2":{"client-analytics":false}}}}`)}, 442 }, 443 }, 444 expectedBidRequest1: &openrtb2.BidRequest{ 445 ID: "test_request", 446 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true}}}}`)}, 447 expectedBidRequest2: &openrtb2.BidRequest{ 448 ID: "test_request", 449 Ext: []byte(`{"prebid":{"analytics":{"adapter2":{"client-analytics":false}}}}`)}, 450 }, 451 { 452 description: "Multiple analytics modules, no clone from evaluate activities, should expect both to have their information to be logged only -- amp", 453 givenEnabledAnalytics: enabledAnalytics{"adapter1": &mockAnalytics{}, "adapter2": &mockAnalytics{}}, 454 givenActivityControl: false, 455 givenAmpObject: &analytics.AmpObject{ 456 Status: http.StatusOK, 457 Errors: nil, 458 AuctionResponse: &openrtb2.BidResponse{}, 459 RequestWrapper: &openrtb_ext.RequestWrapper{ 460 BidRequest: &openrtb2.BidRequest{ 461 ID: "test_request", 462 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true},"adapter2":{"client-analytics":false}}}}`)}, 463 }, 464 }, 465 expectedBidRequest1: &openrtb2.BidRequest{ 466 ID: "test_request", 467 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true}}}}`)}, 468 expectedBidRequest2: &openrtb2.BidRequest{ 469 ID: "test_request", 470 Ext: []byte(`{"prebid":{"analytics":{"adapter2":{"client-analytics":false}}}}`)}, 471 }, 472 { 473 description: "Single analytics module, clone from evaluate activities, should expect both to have their information to be logged only -- amp", 474 givenEnabledAnalytics: enabledAnalytics{"adapter1": &mockAnalytics{}}, 475 givenActivityControl: true, 476 givenAuctionObject: &analytics.AuctionObject{ 477 Status: http.StatusOK, 478 Errors: nil, 479 Response: &openrtb2.BidResponse{}, 480 RequestWrapper: &openrtb_ext.RequestWrapper{ 481 BidRequest: &openrtb2.BidRequest{ 482 ID: "test_request", 483 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true},"adapter2":{"client-analytics":false}}}}`)}, 484 }, 485 }, 486 expectedBidRequest1: &openrtb2.BidRequest{ 487 ID: "test_request", 488 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true}}}}`)}, 489 }, 490 { 491 description: "Single analytics module, adapter name not found, expect entire analytics object to be nil -- video", 492 givenEnabledAnalytics: enabledAnalytics{"unknownAdapter": &mockAnalytics{}}, 493 givenActivityControl: true, 494 givenVideoObject: &analytics.VideoObject{ 495 Status: http.StatusOK, 496 Errors: nil, 497 Response: &openrtb2.BidResponse{}, 498 RequestWrapper: &openrtb_ext.RequestWrapper{ 499 BidRequest: &openrtb2.BidRequest{ 500 ID: "test_request", 501 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true},"adapter2":{"client-analytics":false}}}}`)}, 502 }, 503 }, 504 expectedBidRequest1: &openrtb2.BidRequest{ 505 ID: "test_request", 506 Ext: nil, 507 }, 508 }, 509 } 510 511 for _, test := range tests { 512 t.Run(test.description, func(t *testing.T) { 513 ac := privacy.NewActivityControl(getActivityConfig("sampleModule", test.givenActivityControl, test.givenActivityControl, test.givenActivityControl)) 514 515 var loggedBidReq1, loggedBidReq2 *openrtb2.BidRequest 516 switch { 517 case test.givenAuctionObject != nil: 518 test.givenEnabledAnalytics.LogAuctionObject(test.givenAuctionObject, ac) 519 loggedBidReq1 = test.givenEnabledAnalytics["adapter1"].(*mockAnalytics).lastLoggedAuctionBidRequest 520 if len(test.givenEnabledAnalytics) == 2 { 521 loggedBidReq2 = test.givenEnabledAnalytics["adapter2"].(*mockAnalytics).lastLoggedAuctionBidRequest 522 } 523 case test.givenAmpObject != nil: 524 test.givenEnabledAnalytics.LogAmpObject(test.givenAmpObject, ac) 525 loggedBidReq1 = test.givenEnabledAnalytics["adapter1"].(*mockAnalytics).lastLoggedAmpBidRequest 526 if len(test.givenEnabledAnalytics) == 2 { 527 loggedBidReq2 = test.givenEnabledAnalytics["adapter2"].(*mockAnalytics).lastLoggedAmpBidRequest 528 } 529 case test.givenVideoObject != nil: 530 test.givenEnabledAnalytics.LogVideoObject(test.givenVideoObject, ac) 531 loggedBidReq1 = test.givenEnabledAnalytics["unknownAdapter"].(*mockAnalytics).lastLoggedVideoBidRequest 532 } 533 534 assert.Equal(t, test.expectedBidRequest1, loggedBidReq1) 535 if test.expectedBidRequest2 != nil { 536 assert.Equal(t, test.expectedBidRequest2, loggedBidReq2) 537 } 538 }) 539 } 540 } 541 542 func TestUpdateReqWrapperForAnalytics(t *testing.T) { 543 tests := []struct { 544 description string 545 givenReqWrapper *openrtb_ext.RequestWrapper 546 givenAdapterName string 547 givenIsCloned bool 548 expectedUpdatedBidRequest *openrtb2.BidRequest 549 expectedCloneRequest *openrtb_ext.RequestWrapper 550 }{ 551 { 552 description: "Adapter1 so Adapter2 info should be removed from ext.prebid.analytics", 553 givenReqWrapper: &openrtb_ext.RequestWrapper{ 554 BidRequest: &openrtb2.BidRequest{ 555 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true},"adapter2":{"client-analytics":false}}}}`)}, 556 }, 557 givenAdapterName: "adapter1", 558 givenIsCloned: false, 559 expectedUpdatedBidRequest: &openrtb2.BidRequest{ 560 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true}}}}`), 561 }, 562 expectedCloneRequest: &openrtb_ext.RequestWrapper{ 563 BidRequest: &openrtb2.BidRequest{ 564 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true},"adapter2":{"client-analytics":false}}}}`)}, 565 }, 566 }, 567 { 568 description: "Adapter2 so Adapter1 info should be removed from ext.prebid.analytics", 569 givenReqWrapper: &openrtb_ext.RequestWrapper{ 570 BidRequest: &openrtb2.BidRequest{ 571 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true},"adapter2":{"client-analytics":false}}}}`)}, 572 }, 573 givenAdapterName: "adapter2", 574 givenIsCloned: true, 575 expectedUpdatedBidRequest: &openrtb2.BidRequest{ 576 Ext: []byte(`{"prebid":{"analytics":{"adapter2":{"client-analytics":false}}}}`), 577 }, 578 expectedCloneRequest: nil, 579 }, 580 { 581 description: "Given adapter not found in ext.prebid.analytics so remove entire object", 582 givenReqWrapper: &openrtb_ext.RequestWrapper{ 583 BidRequest: &openrtb2.BidRequest{ 584 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true},"adapter2":{"client-analytics":false}}}}`)}, 585 }, 586 givenAdapterName: "adapterNotFound", 587 givenIsCloned: false, 588 expectedUpdatedBidRequest: &openrtb2.BidRequest{}, 589 expectedCloneRequest: &openrtb_ext.RequestWrapper{ 590 BidRequest: &openrtb2.BidRequest{ 591 Ext: []byte(`{"prebid":{"analytics":{"adapter1":{"client-analytics":true},"adapter2":{"client-analytics":false}}}}`)}, 592 }, 593 }, 594 { 595 description: "Given request is nil, check there are no exceptions", 596 givenReqWrapper: nil, 597 givenAdapterName: "adapter1", 598 givenIsCloned: false, 599 expectedUpdatedBidRequest: nil, 600 expectedCloneRequest: nil, 601 }, 602 } 603 604 for _, test := range tests { 605 t.Run(test.description, func(t *testing.T) { 606 cloneReq := updateReqWrapperForAnalytics(test.givenReqWrapper, test.givenAdapterName, test.givenIsCloned) 607 if test.givenReqWrapper != nil { 608 assert.Equal(t, test.expectedUpdatedBidRequest, test.givenReqWrapper.BidRequest) 609 } 610 assert.Equal(t, test.expectedCloneRequest, cloneReq) 611 }) 612 } 613 }