-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test: Price floors max rules dimensions #3646
Changes from 3 commits
3b230a0
40ee5a8
f72cd25
79bfd0d
4665081
2889b77
e3d885e
f5d3e6f
230c487
3965783
312263b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1299,8 +1299,8 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
and: "Response should contain error" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason : Price floor floorMin " + | ||
"must be positive float, but was $invalidFloorMin "] | ||
["Failed to parse price floors from request, with a reason: Price floor floorMin " + | ||
"must be positive float, but was $invalidFloorMin"] | ||
} | ||
|
||
def "PBS should validate rules from request when request doesn't contain modelGroups"() { | ||
|
@@ -1327,8 +1327,8 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
and: "Response should contain error" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason : Price floor rules " + | ||
"should contain at least one model group "] | ||
["Failed to parse price floors from request, with a reason: Price floor rules " + | ||
"should contain at least one model group"] | ||
} | ||
|
||
def "PBS should validate rules from request when request doesn't contain values"() { | ||
|
@@ -1355,8 +1355,8 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
and: "Response should contain error" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason : Price floor rules values " + | ||
"can't be null or empty, but were null "] | ||
["Failed to parse price floors from request, with a reason: Price floor rules values " + | ||
"can't be null or empty, but were null"] | ||
} | ||
|
||
def "PBS should validate rules from request when modelWeight from request is invalid"() { | ||
|
@@ -1387,8 +1387,8 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
and: "Response should contain error" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason : Price floor modelGroup modelWeight " + | ||
"must be in range(1-100), but was $invalidModelWeight "] | ||
["Failed to parse price floors from request, with a reason: Price floor modelGroup modelWeight " + | ||
"must be in range(1-100), but was $invalidModelWeight"] | ||
where: | ||
invalidModelWeight << [0, MAX_MODEL_WEIGHT + 1] | ||
} | ||
|
@@ -1426,8 +1426,8 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
and: "Response should contain error" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason : Price floor modelGroup modelWeight " + | ||
"must be in range(1-100), but was $invalidModelWeight "] | ||
["Failed to parse price floors from request, with a reason: Price floor modelGroup modelWeight " + | ||
"must be in range(1-100), but was $invalidModelWeight"] | ||
|
||
where: | ||
invalidModelWeight << [0, MAX_MODEL_WEIGHT + 1] | ||
|
@@ -1466,8 +1466,8 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
and: "Response should contain error" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason : Price floor root skipRate " + | ||
"must be in range(0-100), but was $invalidSkipRate "] | ||
["Failed to parse price floors from request, with a reason: Price floor root skipRate " + | ||
"must be in range(0-100), but was $invalidSkipRate"] | ||
|
||
where: | ||
invalidSkipRate << [SKIP_RATE_MIN - 1, SKIP_RATE_MAX + 1] | ||
|
@@ -1506,8 +1506,8 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
and: "Response should contain error" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason : Price floor data skipRate " + | ||
"must be in range(0-100), but was $invalidSkipRate "] | ||
["Failed to parse price floors from request, with a reason: Price floor data skipRate " + | ||
"must be in range(0-100), but was $invalidSkipRate"] | ||
|
||
where: | ||
invalidSkipRate << [SKIP_RATE_MIN - 1, SKIP_RATE_MAX + 1] | ||
|
@@ -1546,8 +1546,8 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
and: "Response should contain error" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason : Price floor modelGroup skipRate " + | ||
"must be in range(0-100), but was $invalidSkipRate "] | ||
["Failed to parse price floors from request, with a reason: Price floor modelGroup skipRate " + | ||
"must be in range(0-100), but was $invalidSkipRate"] | ||
|
||
where: | ||
invalidSkipRate << [SKIP_RATE_MIN - 1, SKIP_RATE_MAX + 1] | ||
|
@@ -1582,8 +1582,8 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
and: "Response should contain error" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason : Price floor modelGroup default " + | ||
"must be positive float, but was $invalidDefaultFloorValue "] | ||
["Failed to parse price floors from request, with a reason: Price floor modelGroup default " + | ||
"must be positive float, but was $invalidDefaultFloorValue"] | ||
} | ||
|
||
def "PBS should not invalidate previously good fetched data when floors provider return invalid data"() { | ||
|
@@ -2046,6 +2046,91 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { | |
} | ||
} | ||
|
||
def "PBS should validate fetch.max-schema-dims from account config"() { | ||
given: "Default BidRequest" | ||
def bidRequest = BidRequest.getDefaultBidRequest(APP) | ||
|
||
and: "Account with enabled fetch, maxSchemaDims in the DB" | ||
def account = getAccountWithEnabledFetch(bidRequest.accountId).tap { | ||
config.auction.priceFloors.fetch.maxSchemaDims = maxSchemaDims | ||
config.auction.priceFloors.fetch.maxSchemaDimsSnakeCase = maxSchemaDimsSnakeCase | ||
} | ||
accountDao.save(account) | ||
|
||
when: "PBS processes auction request" | ||
def response = floorsPbsService.sendAuctionRequest(bidRequest) | ||
|
||
then: "Metric alerts.account_config.ACCOUNT.price-floors should be update" | ||
def metrics = floorsPbsService.sendCollectedMetricsRequest() | ||
assert metrics[INVALID_CONFIG_METRIC(bidRequest.accountId) as String] == 1 | ||
|
||
and: "PBS floors validation failure should not reject the entire auction" | ||
assert !response.seatbid?.isEmpty() | ||
|
||
where: | ||
maxSchemaDims | maxSchemaDimsSnakeCase | ||
null | PBSUtils.randomNegativeNumber | ||
null | PBSUtils.getRandomNumber(20) | ||
PBSUtils.randomNegativeNumber | null | ||
PBSUtils.getRandomNumber(20) | null | ||
} | ||
|
||
def "PBS should validate price-floor.max-rules from account config"() { | ||
given: "Default BidRequest" | ||
def bidRequest = BidRequest.getDefaultBidRequest(APP) | ||
|
||
and: "Account with enabled fetch, maxRules in the DB" | ||
def account = getAccountWithEnabledFetch(bidRequest.accountId).tap { | ||
config.auction.priceFloors.maxRules = maxRules | ||
config.auction.priceFloors.maxRulesSnakeCase = maxRulesSnakeCase | ||
} | ||
accountDao.save(account) | ||
|
||
when: "PBS processes auction request" | ||
def response = floorsPbsService.sendAuctionRequest(bidRequest) | ||
|
||
then: "Metric alerts.account_config.ACCOUNT.price-floors should be update" | ||
def metrics = floorsPbsService.sendCollectedMetricsRequest() | ||
assert metrics[INVALID_CONFIG_METRIC(bidRequest.accountId) as String] == 1 | ||
|
||
and: "PBS floors validation failure should not reject the entire auction" | ||
assert !response.seatbid?.isEmpty() | ||
|
||
where: | ||
maxRules | maxRulesSnakeCase | ||
null | PBSUtils.randomNegativeNumber | ||
PBSUtils.randomNegativeNumber | null | ||
} | ||
|
||
def "PBS should validate price-floor.max-schema-dims from account config"() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
given: "Default BidRequest" | ||
def bidRequest = BidRequest.getDefaultBidRequest(APP) | ||
|
||
and: "Account with enabled fetch, maxSchemaDims in the DB" | ||
def account = getAccountWithEnabledFetch(bidRequest.accountId).tap { | ||
config.auction.priceFloors.maxSchemaDims = maxSchemaDims | ||
config.auction.priceFloors.maxSchemaDimsSnakeCase = maxSchemaDimsSnakeCase | ||
} | ||
accountDao.save(account) | ||
|
||
when: "PBS processes auction request" | ||
def response = floorsPbsService.sendAuctionRequest(bidRequest) | ||
|
||
then: "Metric alerts.account_config.ACCOUNT.price-floors should be update" | ||
def metrics = floorsPbsService.sendCollectedMetricsRequest() | ||
assert metrics[INVALID_CONFIG_METRIC(bidRequest.accountId) as String] == 1 | ||
|
||
and: "PBS floors validation failure should not reject the entire auction" | ||
assert !response.seatbid?.isEmpty() | ||
|
||
where: | ||
maxSchemaDims | maxSchemaDimsSnakeCase | ||
null | PBSUtils.randomNegativeNumber | ||
null | PBSUtils.getRandomNumber(20) | ||
PBSUtils.randomNegativeNumber | null | ||
PBSUtils.getRandomNumber(20) | null | ||
} | ||
|
||
static int convertKilobyteSizeToByte(int kilobyteSize) { | ||
kilobyteSize * 1024 | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ import static org.prebid.server.functional.model.pricefloors.MediaType.VIDEO | |
import static org.prebid.server.functional.model.pricefloors.PriceFloorField.MEDIA_TYPE | ||
import static org.prebid.server.functional.model.pricefloors.PriceFloorField.SITE_DOMAIN | ||
import static org.prebid.server.functional.model.request.auction.DistributionChannel.APP | ||
import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID | ||
|
||
class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { | ||
|
||
|
@@ -511,4 +512,141 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { | |
assert bidderRequest.imp.first().bidFloor == bannerFloorValue | ||
assert bidderRequest.imp.last().bidFloor == videoFloorValue | ||
} | ||
|
||
def "PBS should emit errors when request has more rules than price-floor.max-rules"() { | ||
given: "BidRequest with 2 rules" | ||
def requestFloorValue = PBSUtils.randomFloorValue | ||
def bidRequest = bidRequestWithFloors.tap { | ||
ext.prebid.floors.data.modelGroups[0].values = | ||
[(rule) : requestFloorValue + 0.1, | ||
(new Rule(mediaType: BANNER, country: Country.MULTIPLE).rule): requestFloorValue] | ||
} | ||
|
||
and: "Account with maxRules in the DB" | ||
def accountId = bidRequest.site.publisher.id | ||
def account = getAccountWithEnabledFetch(accountId).tap { | ||
config.auction.priceFloors.maxRules = maxRules | ||
config.auction.priceFloors.maxRulesSnakeCase = maxRulesSnakeCase | ||
} | ||
accountDao.save(account) | ||
|
||
and: "Set bidder response" | ||
def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) | ||
bidResponse.seatbid.first().bid.first().price = requestFloorValue | ||
bidder.setResponse(bidRequest.id, bidResponse) | ||
|
||
when: "PBS processes auction request" | ||
def response = floorsPbsService.sendAuctionRequest(bidRequest) | ||
|
||
then: "PBS should log a errors" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason: " + | ||
"Price floor rules number 2 exceeded its maximum number 1"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not the proper way to configure tests. For any external viewer, it will be hard to understand why it is set to |
||
|
||
where: | ||
maxRules | maxRulesSnakeCase | ||
1 | null | ||
null | 1 | ||
} | ||
|
||
def "PBS should emit errors when request has more schema.fields than floor-config.max-schema-dims"() { | ||
given: "BidRequest with schema 2 fields" | ||
def bidRequest = bidRequestWithFloors | ||
|
||
and: "Account with maxSchemaDims in the DB" | ||
def accountId = bidRequest.site.publisher.id | ||
def account = getAccountWithEnabledFetch(accountId).tap { | ||
config.auction.priceFloors.maxSchemaDims = maxSchemaDims | ||
config.auction.priceFloors.maxSchemaDimsSnakeCase = maxSchemaDimsSnakeCase | ||
} | ||
accountDao.save(account) | ||
|
||
and: "Set bidder response" | ||
def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) | ||
bidder.setResponse(bidRequest.id, bidResponse) | ||
|
||
when: "PBS processes auction request" | ||
def response = floorsPbsService.sendAuctionRequest(bidRequest) | ||
|
||
then: "PBS should log a errors" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason: " + | ||
"Price floor schema dimensions 2 exceeded its maximum number 1"] | ||
|
||
where: | ||
maxSchemaDims | maxSchemaDimsSnakeCase | ||
1 | null | ||
null | 1 | ||
} | ||
|
||
def "PBS should emit errors when request has more schema.fields than fetch.max-schema-dims"() { | ||
given: "Default BidRequest with floorMin" | ||
def bidRequest = bidRequestWithFloors | ||
|
||
and: "Account with disabled fetch in the DB" | ||
def account = getAccountWithEnabledFetch(bidRequest.accountId).tap { | ||
config.auction.priceFloors.fetch.enabled = false | ||
config.auction.priceFloors.maxSchemaDims = maxSchemaDims | ||
config.auction.priceFloors.maxSchemaDimsSnakeCase = maxSchemaDimsSnakeCase | ||
} | ||
accountDao.save(account) | ||
|
||
when: "PBS processes auction request" | ||
def response = floorsPbsService.sendAuctionRequest(bidRequest) | ||
|
||
then: "PBS should log a errors" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason: " + | ||
"Price floor schema dimensions 2 exceeded its maximum number 1"] | ||
|
||
where: | ||
maxSchemaDims | maxSchemaDimsSnakeCase | ||
1 | null | ||
null | 1 | ||
} | ||
|
||
def "PBS should emit errors when stored request has more rules than price-floor.max-rules for amp request"() { | ||
given: "Default AmpRequest" | ||
def ampRequest = AmpRequest.defaultAmpRequest | ||
|
||
and: "Default stored request with 2 rules " | ||
def requestFloorValue = PBSUtils.randomFloorValue | ||
def ampStoredRequest = BidRequest.defaultStoredRequest.tap { | ||
ext.prebid.floors = ExtPrebidFloors.extPrebidFloors | ||
ext.prebid.floors.data.modelGroups[0].values = | ||
[(rule) : requestFloorValue + 0.1, | ||
(new Rule(mediaType: BANNER, country: Country.MULTIPLE).rule): requestFloorValue] | ||
} | ||
def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) | ||
storedRequestDao.save(storedRequest) | ||
|
||
and: "Account with maxRules in the DB" | ||
def account = getAccountWithEnabledFetch(ampRequest.account as String).tap { | ||
config.auction.priceFloors.maxRules = maxRules | ||
config.auction.priceFloors.maxRulesSnakeCase = maxRulesSnakeCase | ||
} | ||
accountDao.save(account) | ||
|
||
and: "Set bidder response" | ||
def bidResponse = BidResponse.getDefaultBidResponse(ampStoredRequest) | ||
bidResponse.seatbid.first().bid.first().price = requestFloorValue | ||
bidder.setResponse(ampStoredRequest.id, bidResponse) | ||
|
||
when: "PBS processes amp request" | ||
def response = floorsPbsService.sendAmpRequest(ampRequest) | ||
|
||
then: "PBS should log a errors" | ||
assert response.ext?.errors[PREBID]*.code == [999] | ||
assert response.ext?.errors[PREBID]*.message == | ||
["Failed to parse price floors from request, with a reason: " + | ||
"Price floor rules number 2 exceeded its maximum number 1"] | ||
|
||
where: | ||
maxRules | maxRulesSnakeCase | ||
1 | null | ||
null | 1 | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also why APP?