Skip to content

Commit 47844e0

Browse files
authored
Tests: EID Permissions extension (#4357)
1 parent 5018a0a commit 47844e0

File tree

3 files changed

+294
-1
lines changed

3 files changed

+294
-1
lines changed

src/test/groovy/org/prebid/server/functional/model/request/auction/Eid.groovy

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,14 @@ class Eid {
2525
it.matchMethod = PBSUtils.randomNumber
2626
}
2727
}
28+
29+
static Eid from(EidPermission eidPermission, List<Uid> uids = [Uid.defaultUid]) {
30+
new Eid().tap {
31+
it.source = eidPermission.source
32+
it.uids = uids
33+
it.inserter = eidPermission.inserter
34+
it.matcher = eidPermission.matcher
35+
it.matchMethod = eidPermission.matchMethod
36+
}
37+
}
2838
}
Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
11
package org.prebid.server.functional.model.request.auction
22

3+
import com.fasterxml.jackson.annotation.JsonProperty
34
import groovy.transform.ToString
45
import org.prebid.server.functional.model.bidder.BidderName
6+
import org.prebid.server.functional.util.PBSUtils
7+
8+
import static org.prebid.server.functional.model.bidder.BidderName.GENERIC
59

610
@ToString(includeNames = true, ignoreNulls = true)
711
class EidPermission {
812

913
String source
10-
List<BidderName> bidders
14+
String inserter
15+
String matcher
16+
@JsonProperty("mm")
17+
Integer matchMethod
18+
List<BidderName> bidders = [GENERIC]
19+
20+
static EidPermission getDefaultEidPermission(List<BidderName> bidders = [GENERIC]) {
21+
new EidPermission().tap {
22+
it.source = PBSUtils.randomString
23+
it.inserter = PBSUtils.randomString
24+
it.matcher = PBSUtils.randomString
25+
it.matchMethod = PBSUtils.randomNumber
26+
it.bidders = bidders
27+
}
28+
}
29+
30+
static EidPermission from(Eid eid, List<BidderName> bidders = [GENERIC]) {
31+
new EidPermission().tap {
32+
it.source = eid.source
33+
it.inserter = eid.inserter
34+
it.matcher = eid.matcher
35+
it.matchMethod = eid.matchMethod
36+
it.bidders = bidders
37+
}
38+
}
1139
}

src/test/groovy/org/prebid/server/functional/tests/EidsSpec.groovy

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ import org.prebid.server.functional.model.request.auction.UserExt
1313
import org.prebid.server.functional.service.PrebidServerException
1414
import org.prebid.server.functional.util.PBSUtils
1515

16+
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST
1617
import static org.prebid.server.functional.model.bidder.BidderName.ALIAS
1718
import static org.prebid.server.functional.model.bidder.BidderName.GENERIC
19+
import static org.prebid.server.functional.model.bidder.BidderName.GENERIC_CAMEL_CASE
1820
import static org.prebid.server.functional.model.bidder.BidderName.OPENX
21+
import static org.prebid.server.functional.model.bidder.BidderName.RUBICON
1922
import static org.prebid.server.functional.model.bidder.BidderName.UNKNOWN
2023
import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD
2124
import static org.prebid.server.functional.model.request.auction.DebugCondition.DISABLED
@@ -338,4 +341,256 @@ class EidsSpec extends BaseSpec {
338341
and: "Bid response shouldn't contain warning"
339342
assert !bidResponse.ext.warnings
340343
}
344+
345+
def "PBS should pass user.eids to all bidders when any of required eid permissions doesn't match"() {
346+
given: "Default BidRequest with eids"
347+
def eidPermission = EidPermission.getDefaultEidPermission([RUBICON])
348+
def userEid = updateEidClosure(Eid.from(eidPermission))
349+
350+
def bidRequest = BidRequest.defaultBidRequest.tap {
351+
user = new User(eids: [userEid])
352+
ext.prebid.data = new ExtRequestPrebidData(eidpermissions: [eidPermission])
353+
}
354+
355+
when: "PBS processes auction request"
356+
def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest)
357+
358+
then: "Bidder request should contain requested eids"
359+
def bidderRequest = bidder.getBidderRequest(bidRequest.id)
360+
assert bidderRequest.user.eids == [userEid]
361+
362+
and: "Bid response shouldn't contain any errors and warnings"
363+
assert !bidResponse.ext.errors
364+
assert !bidResponse.ext.warnings
365+
366+
where:
367+
updateEidClosure << [
368+
{ Eid eid -> eid.tap { it.inserter = null } },
369+
{ Eid eid -> eid.tap { it.matcher = null } },
370+
{ Eid eid -> eid.tap { it.matchMethod = null } },
371+
372+
{ Eid eid -> eid.tap { it.inserter = "" } },
373+
{ Eid eid -> eid.tap { it.matcher = "" } },
374+
375+
{ Eid eid -> eid.tap { it.source = PBSUtils.randomString } },
376+
{ Eid eid -> eid.tap { it.inserter = PBSUtils.randomString } },
377+
{ Eid eid -> eid.tap { it.matcher = PBSUtils.randomString } },
378+
{ Eid eid -> eid.tap { it.matchMethod = PBSUtils.randomNumber } }
379+
]
380+
}
381+
382+
def "PBS shouldn't pass user.eids to unmatched bidders when eidPermissions fields match user.eids"() {
383+
given: "Default BidRequest with eids"
384+
def eidPermissionWithUnmatchedBidder = eidPermission.tap {
385+
bidders = [RUBICON]
386+
}
387+
def userEid = updateEidClosure(eidPermissionWithUnmatchedBidder)
388+
389+
def bidRequest = BidRequest.defaultBidRequest.tap {
390+
user = new User(eids: [userEid])
391+
ext.prebid.data = new ExtRequestPrebidData(eidpermissions: [eidPermissionWithUnmatchedBidder])
392+
}
393+
394+
when: "PBS processes auction request"
395+
def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest)
396+
397+
then: "Bidder request shouldn't contain eids"
398+
def bidderRequest = bidder.getBidderRequest(bidRequest.id)
399+
assert !bidderRequest.user.eids
400+
401+
and: "Bid response shouldn't contain any errors and warnings"
402+
assert !bidResponse.ext.errors
403+
assert !bidResponse.ext.warnings
404+
405+
where:
406+
eidPermission | updateEidClosure
407+
new EidPermission(source: PBSUtils.randomString) | { EidPermission eid -> Eid.from(eid) }
408+
new EidPermission(source: PBSUtils.randomString) | { EidPermission eid -> Eid.getDefaultEid().tap { it.source = eid.source } }
409+
new EidPermission(inserter: PBSUtils.randomString) | { EidPermission eid -> Eid.from(eid).tap { it.source = PBSUtils.randomString } }
410+
new EidPermission(inserter: PBSUtils.randomString) | { EidPermission eid -> Eid.getDefaultEid().tap { it.inserter = eid.inserter } }
411+
new EidPermission(matcher: PBSUtils.randomString) | { EidPermission eid -> Eid.from(eid).tap { it.source = PBSUtils.randomString } }
412+
new EidPermission(matcher: PBSUtils.randomString) | { EidPermission eid -> Eid.getDefaultEid().tap { it.matcher = eid.matcher } }
413+
new EidPermission(matchMethod: PBSUtils.randomNumber) | { EidPermission eid -> Eid.from(eid).tap { it.source = PBSUtils.randomString } }
414+
new EidPermission(matchMethod: PBSUtils.randomNumber) | { EidPermission eid -> Eid.getDefaultEid().tap { it.matchMethod = eid.matchMethod } }
415+
}
416+
417+
def "PBS should filter only unauthorized eids when multiple eids with different permissions are present"() {
418+
given: "Default BidRequest with eids"
419+
def eidPermissionWithUnmatchedBidder = EidPermission.getDefaultEidPermission([RUBICON])
420+
def userEid = Eid.from(eidPermissionWithUnmatchedBidder)
421+
def properEids = [Eid.defaultEid, Eid.defaultEid]
422+
def bidRequest = BidRequest.defaultBidRequest.tap {
423+
user = new User(eids: properEids + userEid)
424+
ext.prebid.data = new ExtRequestPrebidData(eidpermissions: [eidPermissionWithUnmatchedBidder])
425+
}
426+
427+
when: "PBS processes auction request"
428+
def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest)
429+
430+
then: "Bidder request should contain requested eids"
431+
def bidderRequest = bidder.getBidderRequest(bidRequest.id)
432+
assert bidderRequest.user.eids == properEids
433+
434+
and: "Bid response shouldn't contain any errors and warnings"
435+
assert !bidResponse.ext.errors
436+
assert !bidResponse.ext.warnings
437+
}
438+
439+
def "PBS should pass user.eids to matched bidders when eidPermissions fields match user.eids"() {
440+
given: "Default BidRequest with eids"
441+
def eidPermissionAllowingCurrentBidder = eidPermission.tap {
442+
bidders = [[GENERIC, GENERIC_CAMEL_CASE].shuffled().first()]
443+
}
444+
def userEid = updateEidClosure(eidPermissionAllowingCurrentBidder)
445+
446+
def bidRequest = BidRequest.defaultBidRequest.tap {
447+
user = new User(eids: [userEid])
448+
ext.prebid.data = new ExtRequestPrebidData(eidpermissions: [eidPermissionAllowingCurrentBidder])
449+
}
450+
451+
when: "PBS processes auction request"
452+
def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest)
453+
454+
then: "Bidder request should contain requested eids"
455+
def bidderRequest = bidder.getBidderRequest(bidRequest.id)
456+
assert bidderRequest.user.eids == [userEid]
457+
458+
and: "Bid response shouldn't contain any errors and warnings"
459+
assert !bidResponse.ext.errors
460+
assert !bidResponse.ext.warnings
461+
462+
where:
463+
eidPermission | updateEidClosure
464+
new EidPermission(source: PBSUtils.randomString) | { EidPermission eid -> Eid.from(eid) }
465+
new EidPermission(source: PBSUtils.randomString) | { EidPermission eid -> Eid.getDefaultEid().tap { it.source = eid.source } }
466+
new EidPermission(inserter: PBSUtils.randomString) | { EidPermission eid -> Eid.from(eid).tap { it.source = PBSUtils.randomString } }
467+
new EidPermission(inserter: PBSUtils.randomString) | { EidPermission eid -> Eid.getDefaultEid().tap { it.inserter = eid.inserter } }
468+
new EidPermission(matcher: PBSUtils.randomString) | { EidPermission eid -> Eid.from(eid).tap { it.source = PBSUtils.randomString } }
469+
new EidPermission(matcher: PBSUtils.randomString) | { EidPermission eid -> Eid.getDefaultEid().tap { it.matcher = eid.matcher } }
470+
new EidPermission(matchMethod: PBSUtils.randomNumber) | { EidPermission eid -> Eid.from(eid).tap { it.source = PBSUtils.randomString } }
471+
new EidPermission(matchMethod: PBSUtils.randomNumber) | { EidPermission eid -> Eid.getDefaultEid().tap { it.matchMethod = eid.matchMethod } }
472+
}
473+
474+
def "PBS should apply most specific eidPermissions rule when multiple rules match"() {
475+
given: "Default BidRequest with eids"
476+
def userEid = Eid.getDefaultEid()
477+
def moreSpecificEidPermission = moreSpecificPermissionClosure(userEid).tap {
478+
it.bidders = [RUBICON]
479+
}
480+
def lessSpecificEidPermission = lessSpecificPermissionClosure(userEid).tap {
481+
it.bidders = [GENERIC]
482+
}
483+
def bidRequest = BidRequest.defaultBidRequest.tap {
484+
user = new User(eids: [userEid])
485+
ext.prebid.data = new ExtRequestPrebidData(eidpermissions: [moreSpecificEidPermission, lessSpecificEidPermission].shuffled())
486+
}
487+
488+
when: "PBS processes auction request"
489+
def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest)
490+
491+
then: "Bidder request shouldn't contain eids"
492+
def bidderRequest = bidder.getBidderRequest(bidRequest.id)
493+
assert !bidderRequest.user.eids
494+
495+
and: "Bid response shouldn't contain any errors and warnings"
496+
assert !bidResponse.ext.errors
497+
assert !bidResponse.ext.warnings
498+
499+
where:
500+
moreSpecificPermissionClosure | lessSpecificPermissionClosure
501+
({ Eid eid -> EidPermission.from(eid) }) | ({ Eid eid -> EidPermission.from(eid).tap { it.source = null } })
502+
({ Eid eid -> EidPermission.from(eid) }) | ({ Eid eid -> EidPermission.from(eid).tap { it.inserter = null } })
503+
({ Eid eid -> EidPermission.from(eid) }) | ({ Eid eid -> EidPermission.from(eid).tap { it.matcher = null } })
504+
({ Eid eid -> EidPermission.from(eid) }) | ({ Eid eid -> EidPermission.from(eid).tap { it.matchMethod = null } })
505+
({ Eid eid -> EidPermission.from(eid).tap { it.source = null } }) | ({ Eid eid -> new EidPermission(inserter: eid.inserter, matcher: eid.matcher) })
506+
({ Eid eid -> new EidPermission(inserter: eid.inserter, matcher: eid.matcher) }) | ({ Eid eid -> new EidPermission(matchMethod: eid.matchMethod) })
507+
}
508+
509+
def "PBS should allow access to bidder defined in most specific rule when multiple rules match"() {
510+
given: "Default BidRequest with eids"
511+
def userEid = Eid.getDefaultEid()
512+
def moreSpecificEidPermission = moreSpecificPermissionClosure(userEid).tap {
513+
it.bidders = [GENERIC]
514+
}
515+
def lessSpecificEidPermission = lessSpecificPermissionClosure(userEid).tap {
516+
it.bidders = [RUBICON]
517+
}
518+
def bidRequest = BidRequest.defaultBidRequest.tap {
519+
user = new User(eids: [userEid])
520+
ext.prebid.data = new ExtRequestPrebidData(eidpermissions: [moreSpecificEidPermission, lessSpecificEidPermission].shuffled())
521+
}
522+
523+
when: "PBS processes auction request"
524+
def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest)
525+
526+
then: "Bidder request should contain requested eids"
527+
def bidderRequest = bidder.getBidderRequest(bidRequest.id)
528+
assert bidderRequest.user.eids == [userEid]
529+
530+
and: "Bid response shouldn't contain any errors and warnings"
531+
assert !bidResponse.ext.errors
532+
assert !bidResponse.ext.warnings
533+
534+
where:
535+
moreSpecificPermissionClosure | lessSpecificPermissionClosure
536+
({ Eid eid -> EidPermission.from(eid) }) | ({ Eid eid -> EidPermission.from(eid).tap { it.source = null } })
537+
({ Eid eid -> EidPermission.from(eid) }) | ({ Eid eid -> EidPermission.from(eid).tap { it.inserter = null } })
538+
({ Eid eid -> EidPermission.from(eid) }) | ({ Eid eid -> EidPermission.from(eid).tap { it.matcher = null } })
539+
({ Eid eid -> EidPermission.from(eid) }) | ({ Eid eid -> EidPermission.from(eid).tap { it.matchMethod = null } })
540+
({ Eid eid -> EidPermission.from(eid).tap { it.source = null } }) | ({ Eid eid -> new EidPermission(inserter: eid.inserter, matcher: eid.matcher) })
541+
({ Eid eid -> new EidPermission(inserter: eid.inserter, matcher: eid.matcher) }) | ({ Eid eid -> new EidPermission(matchMethod: eid.matchMethod) })
542+
}
543+
544+
def "PBS should apply permissions from any matching rule when specificity is equal"() {
545+
given: "Default BidRequest with eids"
546+
def userEid = Eid.getDefaultEid()
547+
def allowingRule = allowingPermissionClosure(userEid).tap {
548+
it.bidders = [GENERIC]
549+
}
550+
def restrictingRule = restrictingPermissionClosure(userEid).tap {
551+
it.bidders = [RUBICON]
552+
}
553+
def bidRequest = BidRequest.defaultBidRequest.tap {
554+
user = new User(eids: [userEid])
555+
ext.prebid.data = new ExtRequestPrebidData(eidpermissions: [allowingRule, restrictingRule].shuffled())
556+
}
557+
558+
when: "PBS processes auction request"
559+
def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest)
560+
561+
then: "Bidder request should contain requested eids"
562+
def bidderRequest = bidder.getBidderRequest(bidRequest.id)
563+
assert bidderRequest.user.eids == [userEid]
564+
565+
and: "Bid response shouldn't contain any errors and warnings"
566+
assert !bidResponse.ext.errors
567+
assert !bidResponse.ext.warnings
568+
569+
where:
570+
allowingPermissionClosure | restrictingPermissionClosure
571+
({ Eid eid -> new EidPermission(source: eid.source) }) | ({ Eid eid -> new EidPermission(inserter: eid.inserter) })
572+
({ Eid eid -> new EidPermission(matcher: eid.matcher) }) | ({ Eid eid -> new EidPermission(source: eid.source) })
573+
({ Eid eid -> new EidPermission(matchMethod: eid.matchMethod) }) | ({ Eid eid -> new EidPermission(matcher: eid.matcher) })
574+
({ Eid eid -> new EidPermission(source: eid.source, matcher: eid.matcher) }) | ({ Eid eid -> new EidPermission(inserter: eid.inserter, matchMethod: eid.matchMethod) })
575+
({ Eid eid -> new EidPermission(source: eid.source, inserter: eid.inserter) }) | ({ Eid eid -> new EidPermission(matcher: eid.matcher, matchMethod: eid.matchMethod) })
576+
({ Eid eid -> new EidPermission(source: eid.source, matchMethod: eid.matchMethod) }) | ({ Eid eid -> new EidPermission(inserter: eid.inserter, matcher: eid.matcher) })
577+
({ Eid eid -> EidPermission.from(eid).tap { matchMethod = null } }) | ({ Eid eid -> EidPermission.from(eid).tap { matcher = null } })
578+
}
579+
580+
def "PBS should throw an error when all eidPermissions fields are empty"() {
581+
given: "Default bid request with invalid eidPermission"
582+
def bidRequest = BidRequest.defaultBidRequest.tap {
583+
ext.prebid.data = new ExtRequestPrebidData(eidpermissions: [new EidPermission()])
584+
}
585+
586+
when: "PBS processes auction request"
587+
defaultPbsService.sendAuctionRequest(bidRequest)
588+
589+
then: "PBS should throw error"
590+
def exception = thrown(PrebidServerException)
591+
assert exception.statusCode == BAD_REQUEST.code()
592+
assert exception.responseBody == "Invalid request format: " +
593+
"Missing required parameter(s) in request.ext.prebid.data.eidPermissions[]. " +
594+
"Either one or a combination of inserter, source, matcher, or mm should be defined."
595+
}
341596
}

0 commit comments

Comments
 (0)