From bc720e0cc078e267f2f192ce3d922a643d82f2a2 Mon Sep 17 00:00:00 2001 From: markiian Date: Thu, 11 Apr 2024 15:23:11 +0300 Subject: [PATCH 1/3] Add functional tests for `BidResponse validations` --- .../model/request/auction/Asset.groovy | 4 +- .../functional/tests/BidderFormatSpec.groovy | 852 ++++++++++++++++++ 2 files changed, 854 insertions(+), 2 deletions(-) create mode 100644 src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Asset.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Asset.groovy index ff468288f18..4ba1a6bc36f 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Asset.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Asset.groovy @@ -25,11 +25,11 @@ class Asset { } } - static Asset getImgAsset() { + static Asset getImgAsset(String url = PBSUtils.randomString) { new Asset().tap { id = 2 required = 1 - img = new AssetImage(type: 3, w: PBSUtils.randomNumber, h: PBSUtils.randomNumber) + img = new AssetImage(type: 3, w: PBSUtils.randomNumber, h: PBSUtils.randomNumber, url: url) } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy new file mode 100644 index 00000000000..789cc49c806 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy @@ -0,0 +1,852 @@ +package org.prebid.server.functional.tests + +import org.prebid.server.functional.model.bidder.BidderName +import org.prebid.server.functional.model.config.AccountAuctionConfig +import org.prebid.server.functional.model.config.AccountBidValidationConfig +import org.prebid.server.functional.model.config.AccountConfig +import org.prebid.server.functional.model.db.Account +import org.prebid.server.functional.model.db.StoredResponse +import org.prebid.server.functional.model.request.auction.Asset +import org.prebid.server.functional.model.request.auction.Audio +import org.prebid.server.functional.model.request.auction.Banner +import org.prebid.server.functional.model.request.auction.BidRequest +import org.prebid.server.functional.model.request.auction.Format +import org.prebid.server.functional.model.request.auction.Native +import org.prebid.server.functional.model.request.auction.StoredBidResponse +import org.prebid.server.functional.model.request.auction.Video +import org.prebid.server.functional.model.response.auction.Adm +import org.prebid.server.functional.model.response.auction.BidResponse +import org.prebid.server.functional.service.PrebidServerException +import org.prebid.server.functional.util.PBSUtils +import spock.lang.Shared + +import static org.prebid.server.functional.model.AccountStatus.ACTIVE +import static org.prebid.server.functional.model.config.BidValidationEnforcement.ENFORCE +import static org.prebid.server.functional.model.config.BidValidationEnforcement.SKIP +import static org.prebid.server.functional.model.config.BidValidationEnforcement.WARN +import static org.prebid.server.functional.model.response.auction.ErrorType.GENERIC + +class BidderFormatSpec extends BaseSpec { + + @Shared + private static final RANDOM_NUMBER = PBSUtils.randomNumber + + def "PBS should successfully pass when banner.format{w.h} is valid"() { + given: "Default bid request with banner format" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner.format = bannerFormat + } + + when: "Requesting PBS auction" + defaultPbsService.sendAuctionRequest(bidRequest) + + then: "BidResponse should contain the same banner format as on request" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest?.imp[0]?.banner?.format[0].w == bannerFormat[0].w + assert bidderRequest?.imp[0]?.banner?.format[0].h == bannerFormat[0].h + + where: + bannerFormat << [[Format.defaultFormat], + [Format.defaultFormat.tap { + w = 1 + h = 1 + }], + [Format.defaultFormat.tap { + w = PBSUtils.randomNumber + h = PBSUtils.randomNumber + }]] + } + + def "PBS should unsuccessfully pass and throw error due to validation banner.format{w.h} when banner.format{w.h} is invalid"() { + given: "Default bid request with banner format" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner.format = bannerFormat + } + + when: "Requesting PBS auction" + defaultPbsService.sendAuctionRequest(bidRequest) + + then: "PBs should throw error due to banner.format{w.h} validation" + def exception = thrown(PrebidServerException) + assert exception.statusCode == 400 + assert exception.responseBody == "Invalid request format: " + + "Request imp[0].banner.format[0] must define a valid \"h\" and \"w\" properties" + + where: + bannerFormat << [[Format.defaultFormat.tap { w = 0 }], + [Format.defaultFormat.tap { h = 0 }], + [Format.defaultFormat.tap { w = null }], + [Format.defaultFormat.tap { h = null }], + [Format.defaultFormat.tap { w = PBSUtils.randomNegativeNumber }], + [Format.defaultFormat.tap { h = PBSUtils.randomNegativeNumber }]] + } + + def "PBS should successfully pass when banner.{w.h} is valid"() { + given: "Default bid request with banner format" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner = banner + } + + when: "Requesting PBS auction" + defaultPbsService.sendAuctionRequest(bidRequest) + + then: "BidResponse should contain the same banner{w.h} as on request" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest?.imp[0]?.banner?.w == banner.w + assert bidderRequest?.imp[0]?.banner?.h == banner.h + + where: + banner << [new Banner(w: 1, h: 1), new Banner(w: PBSUtils.randomNumber, h: PBSUtils.randomNumber)] + } + + def "PBS should unsuccessfully pass and throw error due to validation banner{w.h} when banner{w.h} is invalid"() { + given: "Default bid request with banner{w.h}" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner = banner + } + + when: "Requesting PBS auction" + defaultPbsService.sendAuctionRequest(bidRequest) + + then: "PBs should throw error due to banner{w.h} validation" + def exception = thrown(PrebidServerException) + assert exception.statusCode == 400 + assert exception.responseBody == "Invalid request format: " + + "request.imp[0].banner has no sizes. Define \"w\" and \"h\", or include \"format\" elements" + + where: + banner << [new Banner(w: 0, h: PBSUtils.randomNumber), + new Banner(w: PBSUtils.randomNumber, h: 0), + new Banner(w: null, h: PBSUtils.randomNumber), + new Banner(w: PBSUtils.randomNumber, h: null), + new Banner(w: PBSUtils.randomNegativeNumber, h: PBSUtils.randomNumber), + new Banner(w: PBSUtils.randomNumber, h: PBSUtils.randomNegativeNumber)] + } + + def "PBS should emit error and metrics when banner-creative-max-size: warn and bid response W or H is larger that request W or H"() { + given: "PBS with banner creative max size" + def pbsService = pbsServiceFactory.getService(["auction.validations.banner-creative-max-size": configCreativeMaxSize]) + + and: "Default bid request with banner format" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner = new Banner().tap { + format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + } + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response with biggest W and H than in bidRequest in DB" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].w = responseWeight + it.seatbid[0].bid[0].h = responseHeight + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + and: "Account in the DB with specified banner max size enforcement" + def accountConfig = new AccountConfig( + auction: new AccountAuctionConfig( + bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), + debugAllow: true)) + def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + accountDao.save(account) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric should increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert metrics["account.${bidRequest.accountId}.response.validation.size.warn"] == 1 + assert metrics["adapter.generic.response.validation.size.warn"] == 1 + + and: "Response should contain error" + assert bidResponse.ext?.errors[GENERIC]*.code == [5] + assert bidResponse.ext?.errors[GENERIC]*.message[0] + == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + "Warning: BidResponse validation `warn`: bidder `${GENERIC}` response triggers creative size " + + "validation for bid ${storedBidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, " + + "referrer=${bidRequest.site.page}, max imp size='${RANDOM_NUMBER}x${RANDOM_NUMBER}', " + + "bid response size='${responseWeight}x${responseHeight}'" + + and: "Bid response should contain weight and height from stored response" + def bid = bidResponse.seatbid[0].bid[0] + assert bid.w == responseWeight + assert bid.h == responseHeight + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight + null | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + null | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + null | WARN.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 + WARN | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + WARN | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + WARN | null | RANDOM_NUMBER | RANDOM_NUMBER + 1 + } + + def "PBS shouldn't emit error and metrics when banner-creative-max-size: skip and bid response W or H is larger that request W or H"() { + given: "PBS with banner creative max size" + def pbsService = pbsServiceFactory.getService(["auction.validations.banner-creative-max-size": configCreativeMaxSize]) + + and: "Default bid request with banner format" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner = new Banner().tap { + format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + } + it.imp.first().ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response with biggest W and H than in bidRequest in DB" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].w = responseWeight + it.seatbid[0].bid[0].h = responseHeight + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + and: "Account in the DB with specified banner max size enforcement" + def accountConfig = new AccountConfig( + auction: new AccountAuctionConfig( + bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), + debugAllow: true)) + def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + accountDao.save(account) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric shouldn't increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert !metrics["account.${bidRequest.accountId}.response.validation.size.warn"] + assert !metrics["account.${bidRequest.accountId}.response.validation.size.err"] + + and: "Response should contain error" + assert !bidResponse.ext?.errors + + and: "Bid response should contain weight and height from stored response" + def bid = bidResponse.seatbid[0].bid[0] + assert bid.w == responseWeight + assert bid.h == responseHeight + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight + null | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + null | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + null | SKIP.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 + SKIP | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + SKIP | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + SKIP | null | RANDOM_NUMBER | RANDOM_NUMBER + 1 + } + + def "PBS should emit error and metrics and remove bid response from consideration when banner-creative-max-size: enforce and bid response W or H is larger that request W or H"() { + given: "PBS with banner creative max size" + def pbsService = pbsServiceFactory.getService(["auction.validations.banner-creative-max-size": configCreativeMaxSize]) + + and: "Default bid request with banner format" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner = new Banner().tap { + format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + } + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response with biggest W and H than in bidRequest in DB" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].w = responseWeight + it.seatbid[0].bid[0].h = responseHeight + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + and: "Account in the DB with specified banner max size enforcement" + def accountConfig = new AccountConfig( + auction: new AccountAuctionConfig( + bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), + debugAllow: true)) + def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + accountDao.save(account) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric should increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert metrics["account.${bidRequest.accountId}.response.validation.size.err"] == 1 + assert metrics["adapter.generic.response.validation.size.err"] == 1 + + and: "Response should contain error" + assert bidResponse.ext?.errors[GENERIC]*.code == [5] + assert bidResponse.ext?.errors[GENERIC]*.message[0] + == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + "Error: BidResponse validation `enforce`: bidder `${GENERIC.value}` response triggers creative size " + + "validation for bid ${storedBidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, " + + "referrer=${bidRequest.site.page}, max imp size='${RANDOM_NUMBER}x${RANDOM_NUMBER}', " + + "bid response size='${responseWeight}x${responseHeight}'" + + and: "Pbs should discard seatBid due to validation" + assert !bidResponse.seatbid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight + null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + null | ENFORCE.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 + ENFORCE | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + ENFORCE | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + ENFORCE | null | RANDOM_NUMBER | RANDOM_NUMBER + 1 + } + + def "PBS shouldn't emit error and metrics when banner-creative-max-size #configCreativeMaxSize and bid response W or H is same that request W or H"() { + given: "PBS with banner creative max size" + def pbsService = pbsServiceFactory.getService(["auction.validations.banner-creative-max-size": configCreativeMaxSize]) + + and: "Default bid request with banner format" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner = new Banner().tap { + format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + } + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response with biggest W and H than in bidRequest in DB" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].w = RANDOM_NUMBER + it.seatbid[0].bid[0].h = RANDOM_NUMBER + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + and: "Account in the DB with specified banner max size enforcement" + def accountConfig = new AccountConfig( + auction: new AccountAuctionConfig( + bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), + debugAllow: true)) + def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + accountDao.save(account) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric shouldn't increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert !metrics["account.${bidRequest.accountId}.response.validation.size.warn"] + assert !metrics["account.${bidRequest.accountId}.response.validation.size.err"] + + and: "Response should contain error" + assert !bidResponse.ext?.errors + + and: "Bid response should contain weight and height from stored response" + def bid = bidResponse.seatbid[0].bid[0] + assert bid.w == RANDOM_NUMBER + assert bid.h == RANDOM_NUMBER + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + accountCretiveMaxSize | configCreativeMaxSize + null | SKIP.value + SKIP | null + ENFORCE | null + null | ENFORCE.value + WARN | null + null | WARN.value + } + + def "PBS shouldn't emit error and metrics when media type isn't banner and banner-creative-max-size #configCreativeMaxSize and bid response W or H is larger that request W or H"() { + given: "PBS with banner creative max size" + def pbsService = pbsServiceFactory.getService(["auction.validations.banner-creative-max-size": configCreativeMaxSize]) + + and: "Default bid request with video W and H" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].video = Video.getDefaultVideo().tap { + w = RANDOM_NUMBER + h = RANDOM_NUMBER + } + imp[0].banner = null + it.imp.first().ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response with biggest W and H than in bidRequest in DB" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].w = responseWeight + it.seatbid[0].bid[0].h = responseHeight + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + and: "Account in the DB with specified banner max size enforcement" + def accountConfig = new AccountConfig( + auction: new AccountAuctionConfig( + bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), + debugAllow: true)) + def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + accountDao.save(account) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric should increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert !metrics["account.${bidRequest.accountId}.response.validation.size.err"] + assert !metrics["adapter.generic.response.validation.size.err"] + + and: "Response shouldn't contain error" + assert !bidResponse.ext?.errors + + and: "Pbs should contain seatBid.bid" + assert bidResponse.seatbid.bid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight + null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + null | ENFORCE.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 + ENFORCE | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + ENFORCE | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + ENFORCE | null | RANDOM_NUMBER | RANDOM_NUMBER + 1 + null | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + null | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + null | SKIP.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 + SKIP | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + SKIP | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + SKIP | null | RANDOM_NUMBER | RANDOM_NUMBER + 1 + null | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + null | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + null | WARN.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 + WARN | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + WARN | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + WARN | null | RANDOM_NUMBER | RANDOM_NUMBER + 1 + } + + def "PBS should emit error and metrics and remove bid response from consideration and account value should take precedence over host when banner-creative-max-size enforce and bid response W or H is larger that request W or H"() { + given: "PBS with banner creative max size" + def pbsService = pbsServiceFactory.getService(["auction.validations.banner-creative-max-size": configCreativeMaxSize]) + + and: "Default bid request with banner format" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner = new Banner().tap { + format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + } + it.imp.first().ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response with biggest W and H than in bidRequest in DB" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].w = responseWeight + it.seatbid[0].bid[0].h = responseHeight + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + and: "Account in the DB with specified banner max size enforcement" + def accountConfig = new AccountConfig( + auction: new AccountAuctionConfig( + bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), + debugAllow: true)) + def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + accountDao.save(account) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric should increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert metrics["account.${bidRequest.accountId}.response.validation.size.err"] == 1 + assert metrics["adapter.generic.response.validation.size.err"] == 1 + + and: "Bid response should contain error" + assert bidResponse.ext?.errors[GENERIC]*.code == [5] + assert bidResponse.ext?.errors[GENERIC]*.message[0] + == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + "Error: BidResponse validation `enforce`: bidder `generic` response triggers creative size " + + "validation for bid ${storedBidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, " + + "referrer=${bidRequest.site.page}, max imp size='${RANDOM_NUMBER}x${RANDOM_NUMBER}', " + + "bid response size='${responseWeight}x${responseHeight}'" + + and: "Pbs should discard seatBid due to validation" + assert !bidResponse.seatbid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + accountCretiveMaxSize | configCreativeMaxSize | responseWeight | responseHeight + ENFORCE | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + ENFORCE | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + ENFORCE | WARN.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 + ENFORCE | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + ENFORCE | null | RANDOM_NUMBER + 1 | RANDOM_NUMBER + ENFORCE | null | RANDOM_NUMBER | RANDOM_NUMBER + 1 + ENFORCE | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 + ENFORCE | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + ENFORCE | SKIP.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 + } + + //todo: Need confirm + def "PBS shouldn't make a validation for audio media type when secure is #secure and secure markUp is #secureMarkup"() { + given: "PBS with secure-markUp: #secureMarkup" + def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": secureMarkup]) + + and: "Default bid request" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].secure = secure + imp[0].banner = null + imp[0].video = null + imp[0].audio = Audio.defaultAudio + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response in DB" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].adm = new Adm(assets: [Asset.getImgAsset("http://secure-assets.${PBSUtils.randomString}.com")]) + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric shouldn't be increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert !metrics["account.${bidRequest.accountId}.response.validation.secure.warn"] + assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.warn"] + assert !metrics["account.${bidRequest.accountId}.response.validation.secure.err"] + assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.err"] + + and: "Bid response should contain error" + assert !bidResponse.ext?.errors + + and: "Pbs should contain seatBid" + assert bidResponse.seatbid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + secure | secureMarkup + 1 | SKIP.value + 1 | ENFORCE.value + 1 | WARN.value + 0 | SKIP.value + 0 | ENFORCE.value + 0 | WARN.value + } + + def "PBS should emit metrics and error when imp[0].secure = 1 and config WARN and bid response adm contain #url"() { + given: "PBS with secure-markUp: warn" + def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": WARN.value]) + + and: "Default bid request" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].secure = 1 + imp[0].banner = banner + imp[0].video = video + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response in DB" + def adm = new Adm(assets: [Asset.getImgAsset("${url}://secure-assets.${PBSUtils.randomString}.com")]) + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].adm = adm + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric should increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert metrics["account.${bidRequest.accountId}.response.validation.secure.warn"] == 1 + assert metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.warn"] == 1 + + and: "Bid response should contain error" + assert bidResponse.ext?.errors[GENERIC]*.code == [5] + assert bidResponse.ext?.errors[GENERIC]*.message[0] + == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + "Warning: BidResponse validation `warn`: bidder `${BidderName.GENERIC.value}` response triggers secure creative " + + "validation for bid ${bidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, referrer=${bidRequest.site.page}," + + " adm=${encode(adm)}" + + and: "Pbs should contain seatBid" + assert bidResponse.seatbid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + url | banner | video + "http%3A" | Banner.defaultBanner | null + "http" | Banner.defaultBanner | null + "http" | null | Video.defaultVideo + "http%3A" | null | Video.defaultVideo + } + + def "PBS should emit metrics and error when imp[0].secure = 1, banner and config SKIP and bid response adm contain #url"() { + given: "PBS with secure-markUp: skip" + def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": SKIP.value]) + + and: "Default bid request with secure 1 and video or banner" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].secure = 1 + imp[0].banner = banner + imp[0].video = video + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response in DB with adm" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].adm = new Adm(assets: [Asset.getImgAsset("${url}://secure-assets.${PBSUtils.randomString}.com")]) + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric should increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert !metrics["account.${bidRequest.accountId}.response.validation.secure.warn"] + assert !metrics["account.${bidRequest.accountId}.response.validation.secure.err"] + assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.warn"] + assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.err"] + + and: "Bid response shouldn't contain error" + assert !bidResponse.ext?.errors + + and: "Pbs should contain seatBid" + assert bidResponse.seatbid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + url | banner | video + "http%3A" | Banner.defaultBanner | null + "http" | Banner.defaultBanner | null + "http" | null | Video.defaultVideo + "http%3A" | null | Video.defaultVideo + } + + def "PBS should emit metrics and error and remove bid response when imp[0].secure = 1, banner and config ENFORCE and bid response adm contain #url"() { + given: "PBS with secure-markUp: enforce" + def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": ENFORCE.value]) + + and: "Default bid request with secure and banner or video" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].secure = 1 + imp[0].banner = banner + imp[0].video = video + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response in DB" + def adm = new Adm(assets: [Asset.getImgAsset("${url}://secure-assets.${PBSUtils.randomString}.com")]) + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].adm = adm + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric should increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert metrics["account.${bidRequest.accountId}.response.validation.secure.err"] == 1 + assert metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.err"] == 1 + + and: "Bid response should contain error" + assert bidResponse.ext?.errors[GENERIC]*.code == [5] + assert bidResponse.ext?.errors[GENERIC]*.message[0] + == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + "Error: BidResponse validation `enforce`: bidder `${BidderName.GENERIC.value}` response triggers secure creative " + + "validation for bid ${storedBidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, referrer=${bidRequest.site.page}," + + " adm=${encode(adm)}" + + and: "Pbs shouldn't contain seatBid" + assert !bidResponse.seatbid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + url | banner | video + "http%3A" | Banner.defaultBanner | null + "http" | Banner.defaultBanner | null + "http" | null | Video.defaultVideo + "http%3A" | null | Video.defaultVideo + } + + def "PBS shouldn't emit errors and metrics when imp[0].secure = #secure and bid response adm contain #url"() { + given: "PBS with secure-markUp" + def pbsService = pbsServiceFactory + .getService(["auction.validations.secure-markup": secureMarkup]) + + and: "Default bid request with secure" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].secure = secure + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response in DB with adm" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].adm = new Adm(assets: [Asset.getImgAsset("${url}://secure-assets.${PBSUtils.randomString}.com")]) + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric shouldn't increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert !metrics["account.${bidRequest.accountId}.response.validation.secure.warn"] + assert !metrics["account.${bidRequest.accountId}.response.validation.secure.err"] + assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.warn"] + assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.err"] + + and: "Bid response shouldn't contain error" + assert !bidResponse.ext?.errors + + and: "Pbs should contain seatBid" + assert bidResponse.seatbid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + url | secure | secureMarkup + "http%3A" | 0 | SKIP.value + "http" | 0 | SKIP.value + "https" | 1 | SKIP.value + "http%3A" | 0 | WARN.value + "http" | 0 | WARN.value + "https" | 1 | WARN.value + "http%3A" | 0 | ENFORCE.value + "http" | 0 | ENFORCE.value + "https" | 1 | ENFORCE.value + } + + //todo: Need confirm + def "PBS shouldn't emit errors and metrics when imp[0].secure = 1 and bid response adm contain #url and secureMarkup #secureMarkup but media type is native"() { + given: "PBS with secure-markUp" + def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": secureMarkup]) + + and: "Default bid request with native" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].secure = 1 + imp[0].banner = null + imp[0].nativeObj = Native.defaultNative + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response in DB with adm" + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].adm = new Adm(assets: [Asset.getImgAsset("${url}://secure-assets.${PBSUtils.randomString}.com")]) + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric shouldn't increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert !metrics["account.${bidRequest.accountId}.response.validation.secure.warn"] + assert !metrics["account.${bidRequest.accountId}.response.validation.secure.err"] + assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.warn"] + assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.err"] + + and: "Bid response shouldn't contain error" + assert !bidResponse.ext?.errors + + and: "Pbs should contain seatBid" + assert bidResponse.seatbid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + url | secureMarkup + "http%3A" | SKIP.value + "http" | SKIP.value + "http%3A" | ENFORCE.value + "http" | ENFORCE.value + "http%3A" | WARN.value + "http" | WARN.value + } + + def "PBS should ignore specified secureMarkup #secureMarkup validation when secure is 0"() { + given: "PBS with secure-markUp" + def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": secureMarkup]) + + and: "Default bid request with stored bid response and secure" + def storedResponseId = PBSUtils.randomNumber + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].secure = 0 + imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } + + and: "Stored bid response in DB with adm" + def adm = new Adm(assets: [Asset.getImgAsset("${url}://secure-assets.${PBSUtils.randomString}.com")]) + def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + it.seatbid[0].bid[0].adm = adm + } + def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) + storedResponseDao.save(storedResponse) + + when: "Requesting PBS auction" + def bidResponse = pbsService.sendAuctionRequest(bidRequest) + + then: "Corresponding metric shouldn't increments" + def metrics = pbsService.sendCollectedMetricsRequest() + assert !metrics["account.${bidRequest.accountId}.response.validation.secure.warn"] + assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.warn"] + + and: "Bid response shouldn't contain error" + assert !bidResponse.ext?.errors + + and: "Pbs should contain seatBid" + assert bidResponse.seatbid + + and: "PBs shouldn't perform a bidder request due to stored bid response" + assert !bidder.getBidderRequests(bidRequest.id) + + where: + secureMarkup | url + WARN.value | "http" + WARN.value | "http%3A" + WARN.value | "https" + ENFORCE.value | "http" + ENFORCE.value | "http%3A" + ENFORCE.value | "https" + SKIP.value | "https" + SKIP.value | "http%3A" + SKIP.value | "https" + } +} From 2ba9aa76d38340859110cc02a71fb22e1a2b031f Mon Sep 17 00:00:00 2001 From: markiian Date: Fri, 12 Apr 2024 11:21:01 +0300 Subject: [PATCH 2/3] Update after confirm few details --- .../functional/tests/BidderFormatSpec.groovy | 98 ++++++------------- 1 file changed, 29 insertions(+), 69 deletions(-) diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy index 789cc49c806..1915a3a85cb 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy @@ -18,6 +18,7 @@ import org.prebid.server.functional.model.response.auction.Adm import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils +import spock.lang.PendingFeature import spock.lang.Shared import static org.prebid.server.functional.model.AccountStatus.ACTIVE @@ -500,7 +501,7 @@ class BidderFormatSpec extends BaseSpec { ENFORCE | SKIP.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 } - //todo: Need confirm + @PendingFeature(reason = "Waiting for confirmation") def "PBS shouldn't make a validation for audio media type when secure is #secure and secure markUp is #secureMarkup"() { given: "PBS with secure-markUp: #secureMarkup" def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": secureMarkup]) @@ -555,12 +556,13 @@ class BidderFormatSpec extends BaseSpec { given: "PBS with secure-markUp: warn" def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": WARN.value]) - and: "Default bid request" + and: "Default bid request with secure and banner or video or nativeObj" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].secure = 1 imp[0].banner = banner imp[0].video = video + imp[0].nativeObj = nativeObj imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } @@ -595,23 +597,26 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: - url | banner | video - "http%3A" | Banner.defaultBanner | null - "http" | Banner.defaultBanner | null - "http" | null | Video.defaultVideo - "http%3A" | null | Video.defaultVideo + url | banner | video | nativeObj + "http%3A" | Banner.defaultBanner | null | null + "http" | Banner.defaultBanner | null | null + "http" | null | Video.defaultVideo | null + "http%3A" | null | Video.defaultVideo | null + "http" | null | null | Native.defaultNative + "http%3A" | null | null | Native.defaultNative } def "PBS should emit metrics and error when imp[0].secure = 1, banner and config SKIP and bid response adm contain #url"() { given: "PBS with secure-markUp: skip" def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": SKIP.value]) - and: "Default bid request with secure 1 and video or banner" + and: "Default bid request with secure and banner or video or nativeObj" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].secure = 1 imp[0].banner = banner imp[0].video = video + imp[0].nativeObj = nativeObj imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } @@ -642,23 +647,26 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: - url | banner | video - "http%3A" | Banner.defaultBanner | null - "http" | Banner.defaultBanner | null - "http" | null | Video.defaultVideo - "http%3A" | null | Video.defaultVideo + url | banner | video | nativeObj + "http%3A" | Banner.defaultBanner | null | null + "http" | Banner.defaultBanner | null | null + "http" | null | Video.defaultVideo | null + "http%3A" | null | Video.defaultVideo | null + "http" | null | null | Native.defaultNative + "http%3A" | null | null | Native.defaultNative } def "PBS should emit metrics and error and remove bid response when imp[0].secure = 1, banner and config ENFORCE and bid response adm contain #url"() { given: "PBS with secure-markUp: enforce" def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": ENFORCE.value]) - and: "Default bid request with secure and banner or video" + and: "Default bid request with secure and banner or video or nativeObj" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].secure = 1 imp[0].banner = banner imp[0].video = video + imp[0].nativeObj = nativeObj imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } @@ -693,11 +701,13 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: - url | banner | video - "http%3A" | Banner.defaultBanner | null - "http" | Banner.defaultBanner | null - "http" | null | Video.defaultVideo - "http%3A" | null | Video.defaultVideo + url | banner | video | nativeObj + "http%3A" | Banner.defaultBanner | null | null + "http" | Banner.defaultBanner | null | null + "http" | null | Video.defaultVideo | null + "http%3A" | null | Video.defaultVideo | null + "http" | null | null | Native.defaultNative + "http%3A" | null | null | Native.defaultNative } def "PBS shouldn't emit errors and metrics when imp[0].secure = #secure and bid response adm contain #url"() { @@ -751,56 +761,6 @@ class BidderFormatSpec extends BaseSpec { "https" | 1 | ENFORCE.value } - //todo: Need confirm - def "PBS shouldn't emit errors and metrics when imp[0].secure = 1 and bid response adm contain #url and secureMarkup #secureMarkup but media type is native"() { - given: "PBS with secure-markUp" - def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": secureMarkup]) - - and: "Default bid request with native" - def storedResponseId = PBSUtils.randomNumber - def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].secure = 1 - imp[0].banner = null - imp[0].nativeObj = Native.defaultNative - imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] - } - - and: "Stored bid response in DB with adm" - def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { - it.seatbid[0].bid[0].adm = new Adm(assets: [Asset.getImgAsset("${url}://secure-assets.${PBSUtils.randomString}.com")]) - } - def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) - storedResponseDao.save(storedResponse) - - when: "Requesting PBS auction" - def bidResponse = pbsService.sendAuctionRequest(bidRequest) - - then: "Corresponding metric shouldn't increments" - def metrics = pbsService.sendCollectedMetricsRequest() - assert !metrics["account.${bidRequest.accountId}.response.validation.secure.warn"] - assert !metrics["account.${bidRequest.accountId}.response.validation.secure.err"] - assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.warn"] - assert !metrics["adapter.${BidderName.GENERIC.value}.response.validation.secure.err"] - - and: "Bid response shouldn't contain error" - assert !bidResponse.ext?.errors - - and: "Pbs should contain seatBid" - assert bidResponse.seatbid - - and: "PBs shouldn't perform a bidder request due to stored bid response" - assert !bidder.getBidderRequests(bidRequest.id) - - where: - url | secureMarkup - "http%3A" | SKIP.value - "http" | SKIP.value - "http%3A" | ENFORCE.value - "http" | ENFORCE.value - "http%3A" | WARN.value - "http" | WARN.value - } - def "PBS should ignore specified secureMarkup #secureMarkup validation when secure is 0"() { given: "PBS with secure-markUp" def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": secureMarkup]) From 2d9f5021aebe738e20be61607a32885d2d844b4a Mon Sep 17 00:00:00 2001 From: osulzhenko Date: Fri, 24 May 2024 18:53:16 +0300 Subject: [PATCH 3/3] minor update --- .../model/request/auction/Banner.groovy | 7 +- .../model/request/auction/Format.groovy | 20 +- .../model/request/auction/Video.groovy | 9 +- .../model/response/auction/Bid.groovy | 20 +- .../testcontainers/scaffolding/Bidder.groovy | 2 +- .../server/functional/tests/AmpSpec.groovy | 14 +- .../functional/tests/BidderFormatSpec.groovy | 281 ++++++++++-------- .../pricefloors/PriceFloorsRulesSpec.groovy | 14 +- 8 files changed, 214 insertions(+), 153 deletions(-) diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Banner.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Banner.groovy index b9d4faf3e16..b4d6c23f4f5 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Banner.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Banner.groovy @@ -1,13 +1,16 @@ package org.prebid.server.functional.model.request.auction +import com.fasterxml.jackson.annotation.JsonProperty import groovy.transform.ToString @ToString(includeNames = true, ignoreNulls = true) class Banner { List format - Integer w - Integer h + @JsonProperty("w") + Integer weight + @JsonProperty("h") + Integer height List btype List battr Integer pos diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Format.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Format.groovy index 0f8236481f5..3508dfa60fe 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Format.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Format.groovy @@ -1,20 +1,26 @@ package org.prebid.server.functional.model.request.auction +import com.fasterxml.jackson.annotation.JsonProperty import groovy.transform.ToString @ToString(includeNames = true, ignoreNulls = true) class Format { - Integer w - Integer h - Integer wratio - Integer hratio - Integer wmin + @JsonProperty("w") + Integer weight + @JsonProperty("h") + Integer height + @JsonProperty("wratio") + Integer weightRatio + @JsonProperty("hratio") + Integer heightRatio + @JsonProperty("wmin") + Integer weightMin static Format getDefaultFormat() { new Format().tap { - w = 300 - h = 250 + weight = 300 + height = 250 } } } diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Video.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Video.groovy index 40b32028217..bc2ef7f5a5c 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Video.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Video.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.model.request.auction +import com.fasterxml.jackson.annotation.JsonProperty import groovy.transform.EqualsAndHashCode import groovy.transform.ToString @@ -14,8 +15,10 @@ class Video { Integer maxseq Integer poddur List protocols - Integer w - Integer h + @JsonProperty("w") + Integer weight + @JsonProperty("h") + Integer height Integer podid Integer podseq List rqddurs @@ -42,6 +45,6 @@ class Video { List companiontype static Video getDefaultVideo() { - new Video(mimes: ["video/mp4"], w: 300, h: 200) + new Video(mimes: ["video/mp4"], weight: 300, height: 200) } } diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/Bid.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/Bid.groovy index 9346c228932..e4fb04de375 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/Bid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/Bid.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.model.response.auction +import com.fasterxml.jackson.annotation.JsonProperty import groovy.transform.EqualsAndHashCode import groovy.transform.ToString import org.prebid.server.functional.model.request.auction.Asset @@ -31,14 +32,19 @@ class Bid implements ObjectMapperWrapper { List apis Integer api Integer protocol - Integer qagmediarating + @JsonProperty("qagmediarating") + Integer qagMediaRating String language String langb String dealid - Integer w - Integer h - Integer wratio - Integer hratio + @JsonProperty("w") + Integer weight + @JsonProperty("h") + Integer height + @JsonProperty("wratio") + Integer weightRatio + @JsonProperty("hratio") + Integer heightRatio Integer exp Integer dur Integer mtype @@ -55,8 +61,8 @@ class Bid implements ObjectMapperWrapper { impid = imp.id price = PBSUtils.getRandomPrice() crid = 1 - h = imp.banner && imp.banner.format ? imp.banner.format.first().h : null - w = imp.banner && imp.banner.format ? imp.banner.format.first().w : null + height = imp.banner && imp.banner.format ? imp.banner.format.first().height : null + weight = imp.banner && imp.banner.format ? imp.banner.format.first().weight : null if (imp.nativeObj || imp.video) { adm = new Adm(assets: [Asset.defaultAsset]) } diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/Bidder.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/Bidder.groovy index 76253716e34..ff0b9f3b4f7 100644 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/Bidder.groovy +++ b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/Bidder.groovy @@ -77,7 +77,7 @@ class Bidder extends NetworkScaffolding { def formatNode = it.get("banner") != null ? it.get("banner").get("format") : null new Imp(id: it.get("id").asText(), banner: formatNode != null - ? new Banner(format: [new Format(w: formatNode.first().get("w").asInt(), h: formatNode.first().get("h").asInt())]) + ? new Banner(format: [new Format(weight: formatNode.first().get("w").asInt(), height: formatNode.first().get("h").asInt())]) : null)} def bidRequest = new BidRequest(id: id, imp: imps) def response = BidResponse.getDefaultBidResponse(bidRequest) diff --git a/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy index 555eec86e4e..9205542bbb8 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy @@ -84,7 +84,7 @@ class AmpSpec extends BaseSpec { then: "Response should contain information from stored response" def price = storedAuctionResponse.bid[0].price assert response.targeting["hb_pb"] == getRoundedTargetingValueWithDefaultPrecision(price) - assert response.targeting["hb_size"] == "${storedAuctionResponse.bid[0].w}x${storedAuctionResponse.bid[0].h}" + assert response.targeting["hb_size"] == "${storedAuctionResponse.bid[0].weight}x${storedAuctionResponse.bid[0].height}" and: "PBS not send request to bidder" assert bidder.getRequestCount(ampStoredRequest.id) == 0 @@ -122,8 +122,8 @@ class AmpSpec extends BaseSpec { assert bidderRequest.site?.page == ampRequest.curl assert bidderRequest.site?.publisher?.id == ampRequest.account.toString() assert bidderRequest.imp[0]?.tagId == ampRequest.slot - assert bidderRequest.imp[0]?.banner?.format*.h == [ampRequest.h, msH] - assert bidderRequest.imp[0]?.banner?.format*.w == [ampRequest.w, msW] + assert bidderRequest.imp[0]?.banner?.format*.height == [ampRequest.h, msH] + assert bidderRequest.imp[0]?.banner?.format*.weight == [ampRequest.w, msW] assert bidderRequest.regs?.gdpr == (ampRequest.gdprApplies ? 1 : 0) } @@ -150,8 +150,8 @@ class AmpSpec extends BaseSpec { then: "Bidder request should contain parameters from request" def bidderRequest = bidder.getBidderRequest(ampStoredRequest.id) - assert bidderRequest.imp[0]?.banner?.format*.h == [ampRequest.oh] - assert bidderRequest.imp[0]?.banner?.format*.w == [ampRequest.ow] + assert bidderRequest.imp[0]?.banner?.format*.height == [ampRequest.oh] + assert bidderRequest.imp[0]?.banner?.format*.weight == [ampRequest.ow] } def "PBS should take parameters from the stored request when it's not specified in the request"() { @@ -176,8 +176,8 @@ class AmpSpec extends BaseSpec { assert bidderRequest.site?.page == ampStoredRequest.site.page assert bidderRequest.site?.publisher?.id == ampStoredRequest.site.publisher.id assert !bidderRequest.imp[0]?.tagId - assert bidderRequest.imp[0]?.banner?.format[0]?.h == ampStoredRequest.imp[0].banner.format[0].h - assert bidderRequest.imp[0]?.banner?.format[0]?.w == ampStoredRequest.imp[0].banner.format[0].w + assert bidderRequest.imp[0]?.banner?.format[0]?.height == ampStoredRequest.imp[0].banner.format[0].height + assert bidderRequest.imp[0]?.banner?.format[0]?.weight == ampStoredRequest.imp[0].banner.format[0].weight assert bidderRequest.regs?.gdpr == ampStoredRequest.regs.ext.gdpr } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy index 1915a3a85cb..f0e0732e16d 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy @@ -4,6 +4,7 @@ import org.prebid.server.functional.model.bidder.BidderName import org.prebid.server.functional.model.config.AccountAuctionConfig import org.prebid.server.functional.model.config.AccountBidValidationConfig import org.prebid.server.functional.model.config.AccountConfig +import org.prebid.server.functional.model.config.BidValidationEnforcement import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.db.StoredResponse import org.prebid.server.functional.model.request.auction.Asset @@ -32,10 +33,10 @@ class BidderFormatSpec extends BaseSpec { @Shared private static final RANDOM_NUMBER = PBSUtils.randomNumber - def "PBS should successfully pass when banner.format{w.h} is valid"() { + def "PBS should successfully pass when banner.format weight and height is valid"() { given: "Default bid request with banner format" def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner.format = bannerFormat + imp[0].banner.format = [new Format(weight: bannerFormatWeight, height: bannerFormatHeight)] } when: "Requesting PBS auction" @@ -43,25 +44,19 @@ class BidderFormatSpec extends BaseSpec { then: "BidResponse should contain the same banner format as on request" def bidderRequest = bidder.getBidderRequest(bidRequest.id) - assert bidderRequest?.imp[0]?.banner?.format[0].w == bannerFormat[0].w - assert bidderRequest?.imp[0]?.banner?.format[0].h == bannerFormat[0].h + assert bidderRequest?.imp[0]?.banner?.format[0].weight == bannerFormatWeight + assert bidderRequest?.imp[0]?.banner?.format[0].height == bannerFormatHeight where: - bannerFormat << [[Format.defaultFormat], - [Format.defaultFormat.tap { - w = 1 - h = 1 - }], - [Format.defaultFormat.tap { - w = PBSUtils.randomNumber - h = PBSUtils.randomNumber - }]] + bannerFormatWeight | bannerFormatHeight + 1 | 1 + PBSUtils.randomNumber | PBSUtils.randomNumber } - def "PBS should unsuccessfully pass and throw error due to validation banner.format{w.h} when banner.format{w.h} is invalid"() { + def "PBS should unsuccessfully pass and throw error due to validation banner.format{w.h} when banner.format weight or height is invalid"() { given: "Default bid request with banner format" def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner.format = bannerFormat + imp[0].banner.format = [new Format(weight: bannerFormatWeight, height: bannerFormatHeight)] } when: "Requesting PBS auction" @@ -74,18 +69,45 @@ class BidderFormatSpec extends BaseSpec { "Request imp[0].banner.format[0] must define a valid \"h\" and \"w\" properties" where: - bannerFormat << [[Format.defaultFormat.tap { w = 0 }], - [Format.defaultFormat.tap { h = 0 }], - [Format.defaultFormat.tap { w = null }], - [Format.defaultFormat.tap { h = null }], - [Format.defaultFormat.tap { w = PBSUtils.randomNegativeNumber }], - [Format.defaultFormat.tap { h = PBSUtils.randomNegativeNumber }]] + bannerFormatWeight | bannerFormatHeight + 0 | PBSUtils.randomNumber + PBSUtils.randomNumber | 0 + null | PBSUtils.randomNumber + PBSUtils.randomNumber | null + PBSUtils.randomNegativeNumber | PBSUtils.randomNumber + PBSUtils.randomNumber | PBSUtils.randomNegativeNumber } - def "PBS should successfully pass when banner.{w.h} is valid"() { + def "PBS should unsuccessfully pass and throw error due to validation banner.format{w.h} when banner.format weight and height is invalid"() { given: "Default bid request with banner format" def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner = banner + imp[0].banner.format = [new Format(weight: bannerFormatWeight, height: bannerFormatHeight)] + } + + when: "Requesting PBS auction" + defaultPbsService.sendAuctionRequest(bidRequest) + + then: "PBs should throw error due to banner.format{w.h} validation" + def exception = thrown(PrebidServerException) + assert exception.statusCode == 400 + assert exception.responseBody == "Invalid request format: Request imp[0].banner.format[0] " + + "should define *either* {w, h} (for static size requirements) " + + "*or* {wmin, wratio, hratio} (for flexible sizes) to be non-zero positive" + + where: + bannerFormatWeight | bannerFormatHeight + 0 | 0 + 0 | null + 0 | PBSUtils.randomNegativeNumber + null | null + null | PBSUtils.randomNegativeNumber + PBSUtils.randomNegativeNumber | PBSUtils.randomNegativeNumber + } + + def "PBS should successfully pass when banner weight and height is valid"() { + given: "Default bid request with banner format" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].banner = new Banner(weight: bannerFormatWeight, height: bannerFormatHeight) } when: "Requesting PBS auction" @@ -93,17 +115,19 @@ class BidderFormatSpec extends BaseSpec { then: "BidResponse should contain the same banner{w.h} as on request" def bidderRequest = bidder.getBidderRequest(bidRequest.id) - assert bidderRequest?.imp[0]?.banner?.w == banner.w - assert bidderRequest?.imp[0]?.banner?.h == banner.h + assert bidderRequest?.imp[0]?.banner?.weight == bannerFormatWeight + assert bidderRequest?.imp[0]?.banner?.height == bannerFormatHeight where: - banner << [new Banner(w: 1, h: 1), new Banner(w: PBSUtils.randomNumber, h: PBSUtils.randomNumber)] + bannerFormatWeight | bannerFormatHeight + 1 | 1 + PBSUtils.randomNumber | PBSUtils.randomNumber } def "PBS should unsuccessfully pass and throw error due to validation banner{w.h} when banner{w.h} is invalid"() { given: "Default bid request with banner{w.h}" def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner = banner + imp[0].banner = new Banner(weight: bannerFormatWeight, height: bannerFormatHeight) } when: "Requesting PBS auction" @@ -116,12 +140,16 @@ class BidderFormatSpec extends BaseSpec { "request.imp[0].banner has no sizes. Define \"w\" and \"h\", or include \"format\" elements" where: - banner << [new Banner(w: 0, h: PBSUtils.randomNumber), - new Banner(w: PBSUtils.randomNumber, h: 0), - new Banner(w: null, h: PBSUtils.randomNumber), - new Banner(w: PBSUtils.randomNumber, h: null), - new Banner(w: PBSUtils.randomNegativeNumber, h: PBSUtils.randomNumber), - new Banner(w: PBSUtils.randomNumber, h: PBSUtils.randomNegativeNumber)] + bannerFormatWeight | bannerFormatHeight + 0 | 0 + 0 | PBSUtils.randomNumber + PBSUtils.randomNumber | 0 + null | null + null | PBSUtils.randomNumber + PBSUtils.randomNumber | null + PBSUtils.randomNegativeNumber | PBSUtils.randomNegativeNumber + PBSUtils.randomNegativeNumber | PBSUtils.randomNumber + PBSUtils.randomNumber | PBSUtils.randomNegativeNumber } def "PBS should emit error and metrics when banner-creative-max-size: warn and bid response W or H is larger that request W or H"() { @@ -131,28 +159,31 @@ class BidderFormatSpec extends BaseSpec { and: "Default bid request with banner format" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner = new Banner().tap { - format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + imp[0].tap { + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) + ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } - imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } and: "Stored bid response with biggest W and H than in bidRequest in DB" + def storedBidId = UUID.randomUUID() def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { - it.seatbid[0].bid[0].w = responseWeight - it.seatbid[0].bid[0].h = responseHeight + it.seatbid[0].bid[0].tap { + it.id = storedBidId + it.weight = responseWeight + it.height = responseHeight + } } def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) storedResponseDao.save(storedResponse) and: "Account in the DB with specified banner max size enforcement" - def accountConfig = new AccountConfig( - auction: new AccountAuctionConfig( - bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), - debugAllow: true)) - def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + def account = getAccountWithSpecifiedBannerMax(bidRequest.accountId, accountCretiveMaxSize) accountDao.save(account) + and: "Flush metrics" + flushMetrics(pbsService) + when: "Requesting PBS auction" def bidResponse = pbsService.sendAuctionRequest(bidRequest) @@ -164,16 +195,16 @@ class BidderFormatSpec extends BaseSpec { and: "Response should contain error" assert bidResponse.ext?.errors[GENERIC]*.code == [5] assert bidResponse.ext?.errors[GENERIC]*.message[0] - == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + == "BidId `${storedBidId}` validation messages: " + "Warning: BidResponse validation `warn`: bidder `${GENERIC}` response triggers creative size " + - "validation for bid ${storedBidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, " + + "validation for bid ${storedBidId}, account=${bidRequest.accountId}, " + "referrer=${bidRequest.site.page}, max imp size='${RANDOM_NUMBER}x${RANDOM_NUMBER}', " + "bid response size='${responseWeight}x${responseHeight}'" and: "Bid response should contain weight and height from stored response" def bid = bidResponse.seatbid[0].bid[0] - assert bid.w == responseWeight - assert bid.h == responseHeight + assert bid.weight == responseWeight + assert bid.height == responseHeight and: "PBs shouldn't perform a bidder request due to stored bid response" assert !bidder.getBidderRequests(bidRequest.id) @@ -195,26 +226,24 @@ class BidderFormatSpec extends BaseSpec { and: "Default bid request with banner format" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner = new Banner().tap { - format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + imp[0].tap { + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) + ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } - it.imp.first().ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } and: "Stored bid response with biggest W and H than in bidRequest in DB" def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { - it.seatbid[0].bid[0].w = responseWeight - it.seatbid[0].bid[0].h = responseHeight + it.seatbid[0].bid[0].tap { + it.weight = responseWeight + it.height = responseHeight + } } def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) storedResponseDao.save(storedResponse) and: "Account in the DB with specified banner max size enforcement" - def accountConfig = new AccountConfig( - auction: new AccountAuctionConfig( - bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), - debugAllow: true)) - def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + def account = getAccountWithSpecifiedBannerMax(bidRequest.accountId, accountCretiveMaxSize) accountDao.save(account) when: "Requesting PBS auction" @@ -230,8 +259,8 @@ class BidderFormatSpec extends BaseSpec { and: "Bid response should contain weight and height from stored response" def bid = bidResponse.seatbid[0].bid[0] - assert bid.w == responseWeight - assert bid.h == responseHeight + assert bid.weight == responseWeight + assert bid.height == responseHeight and: "PBs shouldn't perform a bidder request due to stored bid response" assert !bidder.getBidderRequests(bidRequest.id) @@ -253,26 +282,26 @@ class BidderFormatSpec extends BaseSpec { and: "Default bid request with banner format" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner = new Banner().tap { - format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + imp[0].tap { + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) + ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } - imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } and: "Stored bid response with biggest W and H than in bidRequest in DB" + def storedBidId = UUID.randomUUID() def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { - it.seatbid[0].bid[0].w = responseWeight - it.seatbid[0].bid[0].h = responseHeight + it.seatbid[0].bid[0].tap { + it.id = storedBidId + it.weight = responseWeight + it.height = responseHeight + } } def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) storedResponseDao.save(storedResponse) and: "Account in the DB with specified banner max size enforcement" - def accountConfig = new AccountConfig( - auction: new AccountAuctionConfig( - bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), - debugAllow: true)) - def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + def account = getAccountWithSpecifiedBannerMax(bidRequest.accountId, accountCretiveMaxSize) accountDao.save(account) when: "Requesting PBS auction" @@ -286,9 +315,9 @@ class BidderFormatSpec extends BaseSpec { and: "Response should contain error" assert bidResponse.ext?.errors[GENERIC]*.code == [5] assert bidResponse.ext?.errors[GENERIC]*.message[0] - == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + == "BidId `${storedBidId}` validation messages: " + "Error: BidResponse validation `enforce`: bidder `${GENERIC.value}` response triggers creative size " + - "validation for bid ${storedBidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, " + + "validation for bid ${storedBidId}, account=${bidRequest.accountId}, " + "referrer=${bidRequest.site.page}, max imp size='${RANDOM_NUMBER}x${RANDOM_NUMBER}', " + "bid response size='${responseWeight}x${responseHeight}'" @@ -315,26 +344,24 @@ class BidderFormatSpec extends BaseSpec { and: "Default bid request with banner format" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner = new Banner().tap { - format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + imp[0].tap { + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) + ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } - imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } and: "Stored bid response with biggest W and H than in bidRequest in DB" def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { - it.seatbid[0].bid[0].w = RANDOM_NUMBER - it.seatbid[0].bid[0].h = RANDOM_NUMBER + it.seatbid[0].bid[0].tap { + weight = RANDOM_NUMBER + height = RANDOM_NUMBER + } } def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) storedResponseDao.save(storedResponse) and: "Account in the DB with specified banner max size enforcement" - def accountConfig = new AccountConfig( - auction: new AccountAuctionConfig( - bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), - debugAllow: true)) - def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + def account = getAccountWithSpecifiedBannerMax(bidRequest.accountId, accountCretiveMaxSize) accountDao.save(account) when: "Requesting PBS auction" @@ -350,8 +377,8 @@ class BidderFormatSpec extends BaseSpec { and: "Bid response should contain weight and height from stored response" def bid = bidResponse.seatbid[0].bid[0] - assert bid.w == RANDOM_NUMBER - assert bid.h == RANDOM_NUMBER + assert bid.weight == RANDOM_NUMBER + assert bid.height == RANDOM_NUMBER and: "PBs shouldn't perform a bidder request due to stored bid response" assert !bidder.getBidderRequests(bidRequest.id) @@ -372,29 +399,25 @@ class BidderFormatSpec extends BaseSpec { and: "Default bid request with video W and H" def storedResponseId = PBSUtils.randomNumber - def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].video = Video.getDefaultVideo().tap { - w = RANDOM_NUMBER - h = RANDOM_NUMBER + def bidRequest = BidRequest.getDefaultVideoRequest().tap { + imp[0].tap { + video = new Video(weight: RANDOM_NUMBER, height: RANDOM_NUMBER, mimes: [PBSUtils.randomString]) + ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } - imp[0].banner = null - it.imp.first().ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } and: "Stored bid response with biggest W and H than in bidRequest in DB" def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { - it.seatbid[0].bid[0].w = responseWeight - it.seatbid[0].bid[0].h = responseHeight + it.seatbid[0].bid[0].tap { + weight = responseWeight + height = responseHeight + } } def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) storedResponseDao.save(storedResponse) and: "Account in the DB with specified banner max size enforcement" - def accountConfig = new AccountConfig( - auction: new AccountAuctionConfig( - bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), - debugAllow: true)) - def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + def account = getAccountWithSpecifiedBannerMax(bidRequest.accountId, accountCretiveMaxSize) accountDao.save(account) when: "Requesting PBS auction" @@ -443,26 +466,26 @@ class BidderFormatSpec extends BaseSpec { and: "Default bid request with banner format" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner = new Banner().tap { - format = [new Format(w: RANDOM_NUMBER, h: RANDOM_NUMBER)] + imp[0].tap { + banner = new Banner(format: [new Format(weight: RANDOM_NUMBER, height: RANDOM_NUMBER)]) + ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } - it.imp.first().ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] } and: "Stored bid response with biggest W and H than in bidRequest in DB" + def storedBidId = UUID.randomUUID() def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { - it.seatbid[0].bid[0].w = responseWeight - it.seatbid[0].bid[0].h = responseHeight + it.seatbid[0].bid[0].tap { + it.id = storedBidId + it.weight = responseWeight + it.height = responseHeight + } } def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) storedResponseDao.save(storedResponse) and: "Account in the DB with specified banner max size enforcement" - def accountConfig = new AccountConfig( - auction: new AccountAuctionConfig( - bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: accountCretiveMaxSize), - debugAllow: true)) - def account = new Account(status: ACTIVE, uuid: bidRequest.accountId, config: accountConfig) + def account = getAccountWithSpecifiedBannerMax(bidRequest.accountId, accountCretiveMaxSize) accountDao.save(account) when: "Requesting PBS auction" @@ -476,9 +499,9 @@ class BidderFormatSpec extends BaseSpec { and: "Bid response should contain error" assert bidResponse.ext?.errors[GENERIC]*.code == [5] assert bidResponse.ext?.errors[GENERIC]*.message[0] - == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + == "BidId `${storedBidId}` validation messages: " + "Error: BidResponse validation `enforce`: bidder `generic` response triggers creative size " + - "validation for bid ${storedBidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, " + + "validation for bid ${storedBidId}, account=${bidRequest.accountId}, " + "referrer=${bidRequest.site.page}, max imp size='${RANDOM_NUMBER}x${RANDOM_NUMBER}', " + "bid response size='${responseWeight}x${responseHeight}'" @@ -506,7 +529,7 @@ class BidderFormatSpec extends BaseSpec { given: "PBS with secure-markUp: #secureMarkup" def pbsService = pbsServiceFactory.getService(["auction.validations.secure-markup": secureMarkup]) - and: "Default bid request" + and: "Audio bid request" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { imp[0].secure = secure @@ -567,9 +590,13 @@ class BidderFormatSpec extends BaseSpec { } and: "Stored bid response in DB" + def storedBidId = UUID.randomUUID() def adm = new Adm(assets: [Asset.getImgAsset("${url}://secure-assets.${PBSUtils.randomString}.com")]) def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { - it.seatbid[0].bid[0].adm = adm + it.seatbid[0].bid[0].tap { + it.id = storedBidId + it.adm = adm + } } def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) storedResponseDao.save(storedResponse) @@ -585,9 +612,9 @@ class BidderFormatSpec extends BaseSpec { and: "Bid response should contain error" assert bidResponse.ext?.errors[GENERIC]*.code == [5] assert bidResponse.ext?.errors[GENERIC]*.message[0] - == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + == "BidId `${storedBidId}` validation messages: " + "Warning: BidResponse validation `warn`: bidder `${BidderName.GENERIC.value}` response triggers secure creative " + - "validation for bid ${bidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, referrer=${bidRequest.site.page}," + + "validation for bid ${storedBidId}, account=${bidRequest.accountId}, referrer=${bidRequest.site.page}," + " adm=${encode(adm)}" and: "Pbs should contain seatBid" @@ -671,9 +698,13 @@ class BidderFormatSpec extends BaseSpec { } and: "Stored bid response in DB" + def storedBidId = UUID.randomUUID() def adm = new Adm(assets: [Asset.getImgAsset("${url}://secure-assets.${PBSUtils.randomString}.com")]) def storedBidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { - it.seatbid[0].bid[0].adm = adm + it.seatbid[0].bid[0].tap { + it.id = storedBidId + it.adm = adm + } } def storedResponse = new StoredResponse(responseId: storedResponseId, storedBidResponse: storedBidResponse) storedResponseDao.save(storedResponse) @@ -689,9 +720,9 @@ class BidderFormatSpec extends BaseSpec { and: "Bid response should contain error" assert bidResponse.ext?.errors[GENERIC]*.code == [5] assert bidResponse.ext?.errors[GENERIC]*.message[0] - == "BidId `${storedBidResponse.seatbid[0].bid[0].id}` validation messages: " + + == "BidId `${storedBidId}` validation messages: " + "Error: BidResponse validation `enforce`: bidder `${BidderName.GENERIC.value}` response triggers secure creative " + - "validation for bid ${storedBidResponse.seatbid[0].bid[0].id}, account=${bidRequest.accountId}, referrer=${bidRequest.site.page}," + + "validation for bid ${storedBidId}, account=${bidRequest.accountId}, referrer=${bidRequest.site.page}," + " adm=${encode(adm)}" and: "Pbs shouldn't contain seatBid" @@ -718,8 +749,10 @@ class BidderFormatSpec extends BaseSpec { and: "Default bid request with secure" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].secure = secure - imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + imp[0].tap { + it.secure = secure + it.ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } } and: "Stored bid response in DB with adm" @@ -768,8 +801,10 @@ class BidderFormatSpec extends BaseSpec { and: "Default bid request with stored bid response and secure" def storedResponseId = PBSUtils.randomNumber def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].secure = 0 - imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + imp[0].tap { + secure = 0 + ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: BidderName.GENERIC)] + } } and: "Stored bid response in DB with adm" @@ -809,4 +844,12 @@ class BidderFormatSpec extends BaseSpec { SKIP.value | "http%3A" SKIP.value | "https" } + + private static Account getAccountWithSpecifiedBannerMax(String accountId, BidValidationEnforcement bannerMaxSizeEnforcement) { + def accountConfig = new AccountConfig( + auction: new AccountAuctionConfig( + bidValidations: new AccountBidValidationConfig(bannerMaxSizeEnforcement: bannerMaxSizeEnforcement), + debugAllow: true)) + new Account(status: ACTIVE, uuid: accountId, config: accountConfig) + } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsRulesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsRulesSpec.groovy index b0c4a101279..979eac4474b 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsRulesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsRulesSpec.groovy @@ -284,8 +284,8 @@ class PriceFloorsRulesSpec extends PriceFloorsBaseSpec { def higherWidth = lowerWidth + 1 def higherHigh = lowerHigh + 1 def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner.format = [new Format(w: lowerWidth, h: lowerHigh), - new Format(w: higherWidth, h: higherHigh)] + imp[0].banner.format = [new Format(weight: lowerWidth, height: lowerHigh), + new Format(weight: higherWidth, height: higherHigh)] } and: "Account with enabled fetch, fetch.url in the DB" @@ -352,20 +352,20 @@ class PriceFloorsRulesSpec extends PriceFloorsBaseSpec { mediaType | impClosure org.prebid.server.functional.model.response.auction.MediaType.BANNER | { int widthVal, int heightVal -> Imp.getDefaultImpression(mediaType).tap { - banner.format = [new Format(w: widthVal, h: heightVal)] + banner.format = [new Format(weight: widthVal, height: heightVal)] } } org.prebid.server.functional.model.response.auction.MediaType.BANNER | { int widthVal, int heightVal -> Imp.getDefaultImpression(mediaType).tap { banner.format = null - banner.w = widthVal - banner.h = heightVal + banner.weight = widthVal + banner.height = heightVal } } org.prebid.server.functional.model.response.auction.MediaType.VIDEO | { int widthVal, int heightVal -> Imp.getDefaultImpression(mediaType).tap { - video.w = widthVal - video.h = heightVal + video.weight = widthVal + video.height = heightVal } } }