@@ -24,6 +24,7 @@ import static org.prebid.server.functional.model.pricefloors.Country.USA
2424import static org.prebid.server.functional.model.request.GppSectionId.US_CA_V1
2525import static org.prebid.server.functional.model.request.GppSectionId.US_CO_V1
2626import static org.prebid.server.functional.model.request.auction.ActivityType.FETCH_BIDS
27+ import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_EIDS
2728import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_PRECISE_GEO
2829import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_TID
2930import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_UFPD
@@ -42,6 +43,9 @@ class ActivityTraceLogSpec extends PrivacyBaseSpec {
4243
4344 private static final def PROCESSING_ACTIVITY_TRACE = [" Processing rule." ]
4445
46+ private final static Integer MIN_PERCENT_AB = 0
47+ private final static Integer MAX_PERCENT_AB = 100
48+
4549 def " PBS auction shouldn't log info about activity in response when ext.prebid.trace=null" () {
4650 given : " Default basic generic BidRequest"
4751 def accountId = PBSUtils . randomNumber as String
@@ -398,10 +402,223 @@ class ActivityTraceLogSpec extends PrivacyBaseSpec {
398402 allow << [false , true ]
399403 }
400404
401- private List<ActivityInfrastructure > getActivityByName (List<ActivityInfrastructure > activityInfrastructures ,
402- ActivityType activity ) {
405+ def " PBS auction should log info about activity in response when ext.prebid.trace=verbose and skipRate=#skipRate" () {
406+ given : " Default bid request"
407+ def accountId = PBSUtils . randomNumber as String
408+ def bidRequest = BidRequest . defaultBidRequest. tap {
409+ ext. prebid. trace = VERBOSE
410+ device = new Device (geo : new Geo (country : USA , region : ALABAMA . abbreviation))
411+ regs. ext = new RegsExt (gpc : PBSUtils . randomString)
412+ regs. gppSid = [US_CA_V1 . intValue]
413+ regs. gpp = new UsNatV1Consent.Builder (). setGpc(true ). build()
414+ setAccountId(accountId)
415+ }
416+
417+ and : " Set up activities"
418+ def gpc = PBSUtils . randomString
419+ def condition = Condition . baseCondition. tap {
420+ it. gpc = gpc
421+ it. geo = [CAN . withState(ARIZONA )]
422+ }
423+ def activityRule = ActivityRule . getDefaultActivityRule(condition). tap {
424+ it. privacyRegulation = [IAB_US_GENERAL ]
425+ }
426+ def activity = Activity . getDefaultActivity([activityRule])
427+ def activities = AllowActivities . getDefaultAllowActivities(FETCH_BIDS , activity)
428+
429+ and : " Account gpp configuration"
430+ def accountGppConfig = new AccountGppConfig (code : IAB_US_GENERAL , enabled : true , skipRate : skipRate)
431+
432+ and : " Save account with allow activities setup"
433+ def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig])
434+ accountDao. save(account)
435+
436+ when : " PBS processes auction requests"
437+ def bidResponse = activityPbsService. sendAuctionRequest(bidRequest)
438+
439+ then : " Bid response should contain verbose info in debug"
440+ def infrastructure = bidResponse. ext. debug. trace. activityInfrastructure
441+ def ruleConfigurations = findProcessingRule(infrastructure, FETCH_BIDS ). ruleConfiguration. and
442+ assert ruleConfigurations. size() == 1
443+ assert ruleConfigurations. first. and. every { it != null }
444+
445+ and : " Should not contain information that module was skipped"
446+ verifyAll(ruleConfigurations. first) {
447+ ! it. privacyModule
448+ ! it. skipped
449+ ! it. result
450+ }
451+
452+ where :
453+ skipRate << [null , MIN_PERCENT_AB ]
454+ }
455+
456+ def " PBS auction should log info about module skip in response when ext.prebid.trace=verbose and skipRate is max" () {
457+ given : " Default bid request"
458+ def accountId = PBSUtils . randomNumber as String
459+ def bidRequest = BidRequest . defaultBidRequest. tap {
460+ ext. prebid. trace = VERBOSE
461+ device = new Device (geo : new Geo (country : USA , region : ALABAMA . abbreviation))
462+ regs. ext = new RegsExt (gpc : PBSUtils . randomString)
463+ regs. gppSid = [US_CA_V1 . intValue]
464+ regs. gpp = new UsNatV1Consent.Builder (). setGpc(true ). build()
465+ setAccountId(accountId)
466+ }
467+
468+ and : " Set up activities"
469+ def gpc = PBSUtils . randomString
470+ def condition = Condition . baseCondition. tap {
471+ it. gpc = gpc
472+ it. geo = [CAN . withState(ARIZONA )]
473+ }
474+ def activityRule = ActivityRule . getDefaultActivityRule(condition). tap {
475+ it. privacyRegulation = [IAB_US_GENERAL ]
476+ }
477+ def activity = Activity . getDefaultActivity([activityRule], defaultAction)
478+ def activities = AllowActivities . getDefaultAllowActivities(FETCH_BIDS , activity)
479+
480+ and : " Account gpp configuration"
481+ def accountGppConfig = new AccountGppConfig (code : IAB_US_GENERAL , enabled : true , skipRate : MAX_PERCENT_AB )
482+
483+ and : " Save account with allow activities setup"
484+ def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig])
485+ accountDao. save(account)
486+
487+ when : " PBS processes auction requests"
488+ def bidResponse = activityPbsService. sendAuctionRequest(bidRequest)
489+
490+ then : " Bid response should not contain verbose info in debug"
491+ def infrastructure = bidResponse. ext. debug. trace. activityInfrastructure
492+ def ruleConfigurations = findProcessingRule(infrastructure, FETCH_BIDS ). ruleConfiguration. and
493+ assert ruleConfigurations. size() == 1
494+ assert ruleConfigurations. first. and. every { it == null }
495+
496+ and : " Should contain information that module was skipped"
497+ verifyAll(ruleConfigurations. first) {
498+ it. privacyModule == ' iab.usgeneral'
499+ it. skipped == ' true'
500+ it. result == ' ABSTAIN'
501+ }
502+
503+ where :
504+ defaultAction << [false , true ]
505+ }
506+
507+ def " PBS auction should log consistently for each activity about skips modules in response" () {
508+ given : " Default bid request"
509+ def accountId = PBSUtils . randomNumber as String
510+ def bidRequest = BidRequest . defaultBidRequest. tap {
511+ ext. prebid. trace = VERBOSE
512+ device = new Device (geo : new Geo (country : USA , region : ALABAMA . abbreviation))
513+ regs. ext = new RegsExt (gpc : PBSUtils . randomString)
514+ regs. gppSid = [US_CA_V1 . intValue]
515+ regs. gpp = new UsNatV1Consent.Builder (). build()
516+ setAccountId(accountId)
517+ }
518+
519+ and : " Set up activities"
520+ def gpc = PBSUtils . randomString
521+ def condition = Condition . baseCondition. tap {
522+ it. gpc = gpc
523+ it. geo = [CAN . withState(ARIZONA )]
524+ }
525+ def activityRule = ActivityRule . getDefaultActivityRule(condition). tap {
526+ it. privacyRegulation = [IAB_US_GENERAL ]
527+ }
528+ def activity = Activity . getDefaultActivity([activityRule])
529+ def activities = new AllowActivities (
530+ syncUser : activity,
531+ fetchBids : activity,
532+ enrichUfpd : activity,
533+ reportAnalytics : activity,
534+ transmitUfpd : activity,
535+ transmitEids : activity,
536+ transmitPreciseGeo : activity,
537+ transmitTid : activity,
538+ )
539+
540+ and : " Account gpp configuration"
541+ def skipRate = PBSUtils . getRandomNumber(MIN_PERCENT_AB , MAX_PERCENT_AB )
542+ def accountGppConfig = new AccountGppConfig (code : IAB_US_GENERAL , enabled : true , skipRate : skipRate)
543+
544+ and : " Save account with allow activities setup"
545+ def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig])
546+ accountDao. save(account)
547+
548+ when : " PBS processes auction requests"
549+ def bidResponse = activityPbsService. sendAuctionRequest(bidRequest)
550+
551+ then : " Bid response should log consistently for each activity about skips"
552+ def infrastructure = bidResponse. ext. debug. trace. activityInfrastructure
553+ def fetchBidsLogs = findProcessingRule(infrastructure, FETCH_BIDS ). ruleConfiguration. and
554+ def transmitUfpdLogs = findProcessingRule(infrastructure, TRANSMIT_UFPD ). ruleConfiguration. and
555+ def transmitEidsLogs = findProcessingRule(infrastructure, TRANSMIT_EIDS ). ruleConfiguration. and
556+ def transmitPreciseGeoLogs = findProcessingRule(infrastructure, TRANSMIT_PRECISE_GEO ). ruleConfiguration. and
557+ def transmitTidLogs = findProcessingRule(infrastructure, TRANSMIT_TID ). ruleConfiguration. and
558+ verifyAll ([fetchBidsLogs, transmitUfpdLogs, transmitEidsLogs, transmitPreciseGeoLogs, transmitTidLogs]) {
559+ it. privacyModule. toSet(). size() == 1
560+ it. skipped. toSet(). size() == 1
561+ it. result. toSet(). size() == 1
562+ }
563+ }
564+
565+ def " PBS auction shouldn't emit errors or warnings when skip rate is out of borders" () {
566+ given : " Default bid request"
567+ def accountId = PBSUtils . randomNumber as String
568+ def bidRequest = BidRequest . defaultBidRequest. tap {
569+ ext. prebid. trace = VERBOSE
570+ device = new Device (geo : new Geo (country : USA , region : ALABAMA . abbreviation))
571+ regs. ext = new RegsExt (gpc : PBSUtils . randomString)
572+ regs. gppSid = [US_CA_V1 . intValue]
573+ regs. gpp = new UsNatV1Consent.Builder (). setGpc(true ). build()
574+ setAccountId(accountId)
575+ }
576+
577+ and : " Set up activities"
578+ def gpc = PBSUtils . randomString
579+ def condition = Condition . baseCondition. tap {
580+ it. gpc = gpc
581+ it. geo = [CAN . withState(ARIZONA )]
582+ }
583+ def activityRule = ActivityRule . getDefaultActivityRule(condition). tap {
584+ it. privacyRegulation = [IAB_US_GENERAL ]
585+ }
586+ def activity = Activity . getDefaultActivity([activityRule])
587+ def activities = AllowActivities . getDefaultAllowActivities(FETCH_BIDS , activity)
588+
589+ and : " Account gpp configuration"
590+ def accountGppConfig = new AccountGppConfig (code : IAB_US_GENERAL , enabled : true , skipRate : skipRate)
591+
592+ and : " Save account with allow activities setup"
593+ def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig])
594+ accountDao. save(account)
595+
596+ when : " PBS processes auction requests"
597+ def bidResponse = activityPbsService. sendAuctionRequest(bidRequest)
598+
599+ then : " Response should not contain error"
600+ assert ! bidResponse. ext?. errors
601+ assert ! bidResponse. ext?. warnings
602+
603+ where :
604+ skipRate << [Integer . MIN_VALUE , Integer . MAX_VALUE ]
605+ }
606+
607+ private static List<ActivityInfrastructure > getActivityByName (List<ActivityInfrastructure > activityInfrastructures ,
608+ ActivityType activity ) {
403609 def firstIndex = activityInfrastructures. findLastIndexOf { it -> it. activity == activity }
404610 def lastIndex = activityInfrastructures. findIndexOf { it -> it. activity == activity }
405611 activityInfrastructures[new IntRange (true , firstIndex, lastIndex)]
406612 }
613+
614+ private static ActivityInfrastructure findProcessingRule (List<ActivityInfrastructure > infrastructures , ActivityType activity ) {
615+ def matchingActivities = getActivityByName(infrastructures, activity)
616+ .findAll { PROCESSING_ACTIVITY_TRACE . contains(it. description) }
617+
618+ if (matchingActivities. size() != 1 ) {
619+ throw new IllegalStateException (" Expected a single processing activity, but found ${ matchingActivities.size()} " )
620+ }
621+
622+ matchingActivities. first()
623+ }
407624}
0 commit comments