diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index 40c8ff86bde..319dd51084f 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -1,6 +1,5 @@ package org.prebid.server.auction; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.App; @@ -56,7 +55,6 @@ import org.prebid.server.bidder.model.Price; import org.prebid.server.cookie.UidsCookie; import org.prebid.server.exception.InvalidRequestException; -import org.prebid.server.exception.PreBidException; import org.prebid.server.execution.timeout.Timeout; import org.prebid.server.execution.timeout.TimeoutFactory; import org.prebid.server.floors.PriceFloorAdjuster; @@ -79,8 +77,6 @@ import org.prebid.server.proto.openrtb.ext.request.ExtApp; import org.prebid.server.proto.openrtb.ext.request.ExtBidderConfigOrtb; import org.prebid.server.proto.openrtb.ext.request.ExtDooh; -import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; -import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebidFloors; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidBidderConfig; @@ -126,6 +122,8 @@ public class ExchangeService { private static final Integer DEFAULT_MULTIBID_LIMIT_MAX = 9; private static final String EID_ALLOWED_FOR_ALL_BIDDERS = "*"; private static final BigDecimal THOUSAND = BigDecimal.valueOf(1000); + private static final Set BIDDER_FIELDS_EXCEPTION_LIST = Set.of( + "adunitcode", "storedrequest", "options", "is_rewarded_inventory"); private final double logSamplingRate; private final BidderCatalog bidderCatalog; @@ -870,7 +868,7 @@ private Imp prepareImp(Imp imp, return imp.toBuilder() .bidfloor(adjustedPrice.getValue()) .bidfloorcur(adjustedPrice.getCurrency()) - .ext(prepareImpExt(bidder, imp.getExt(), adjustedPrice.getValue(), transmitTid, useFirstPartyData)) + .ext(prepareImpExt(bidder, imp.getExt(), transmitTid, useFirstPartyData)) .build(); } @@ -885,11 +883,10 @@ private Price resolveBidPrice(Imp imp, private ObjectNode prepareImpExt(String bidder, ObjectNode impExt, - BigDecimal adjustedFloor, boolean transmitTid, boolean useFirstPartyData) { final JsonNode bidderNode = bidderParamsFromImpExt(impExt).get(bidder); - final JsonNode impExtPrebid = prepareImpExt(impExt.get(PREBID_EXT), adjustedFloor); + final JsonNode impExtPrebid = cleanUpImpExtPrebid(impExt.get(PREBID_EXT)); Optional.ofNullable(impExtPrebid).ifPresentOrElse( ext -> impExt.set(PREBID_EXT, ext), () -> impExt.remove(PREBID_EXT)); @@ -901,33 +898,22 @@ private ObjectNode prepareImpExt(String bidder, return fpdResolver.resolveImpExt(impExt, useFirstPartyData); } - private JsonNode prepareImpExt(JsonNode extImpPrebidNode, BigDecimal adjustedFloor) { - if (extImpPrebidNode.size() <= 1) { + private JsonNode cleanUpImpExtPrebid(JsonNode extImpPrebid) { + if (extImpPrebid.size() <= 1) { return null; } - final ExtImpPrebid extImpPrebid = extImpPrebid(extImpPrebidNode); - final ExtImpPrebidFloors floors = extImpPrebid.getFloors(); - final ExtImpPrebidFloors updatedFloors = floors != null - ? ExtImpPrebidFloors.of(floors.getFloorRule(), - floors.getFloorRuleValue(), - adjustedFloor, - floors.getFloorMin(), - floors.getFloorMinCur()) - : null; - - return mapper.mapper().valueToTree(extImpPrebid(extImpPrebidNode).toBuilder() - .floors(updatedFloors) - .bidder(null) - .build()); - } + final Iterator fieldsIterator = extImpPrebid.fieldNames(); + final ObjectNode modifiedExtImpPrebid = extImpPrebid.deepCopy(); - private ExtImpPrebid extImpPrebid(JsonNode extImpPrebid) { - try { - return mapper.mapper().treeToValue(extImpPrebid, ExtImpPrebid.class); - } catch (JsonProcessingException e) { - throw new PreBidException("Error decoding imp.ext.prebid: " + e.getMessage(), e); + while (fieldsIterator.hasNext()) { + final String fieldName = fieldsIterator.next(); + if (!BIDDER_FIELDS_EXCEPTION_LIST.contains(fieldName)) { + modifiedExtImpPrebid.remove(fieldName); + } } + + return modifiedExtImpPrebid; } private App prepareApp(App app, ObjectNode fpdApp, boolean useFirstPartyData) { diff --git a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java index ebc7a7dccf4..0692c72f36d 100644 --- a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java +++ b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java @@ -1,6 +1,5 @@ package org.prebid.server.bidder.rubicon; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -52,7 +51,6 @@ import org.prebid.server.bidder.rubicon.proto.request.RubiconExtPrebidBiddersBidder; import org.prebid.server.bidder.rubicon.proto.request.RubiconExtPrebidBiddersBidderDebug; import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExt; -import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExtPrebid; import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExtRp; import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExtRpRtb; import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExtRpTrack; @@ -89,7 +87,6 @@ import org.prebid.server.proto.openrtb.ext.request.ExtDevice; import org.prebid.server.proto.openrtb.ext.request.ExtImpContextDataAdserver; import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; -import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebidFloors; import org.prebid.server.proto.openrtb.ext.request.ExtPublisher; import org.prebid.server.proto.openrtb.ext.request.ExtRegs; import org.prebid.server.proto.openrtb.ext.request.ExtRegsDsa; @@ -507,16 +504,7 @@ private Imp makeImp(Imp imp, final Imp.ImpBuilder builder = imp.toBuilder() .metric(makeMetrics(imp)) .ext(mapper.mapper().valueToTree( - makeImpExt( - imp, - bidRequest, - extImpRubicon, - resolvedFormats, - site, - app, - extRequest, - ipfCurrency, - priceFloorResult))); + makeImpExt(imp, extImpRubicon, resolvedFormats, site, app, extRequest))); final BigDecimal resolvedBidFloor = ipfFloor != null ? convertToXAPICurrency(ipfFloor, ipfCurrency, imp, bidRequest) @@ -672,18 +660,11 @@ private BigDecimal convertBidFloorCurrency(BigDecimal bidFloor, } private RubiconImpExt makeImpExt(Imp imp, - BidRequest bidRequest, ExtImpRubicon rubiconImpExt, Set formats, Site site, App app, - ExtRequest extRequest, - String ipfResolvedCurrency, - PriceFloorResult priceFloorResult) { - - final RubiconImpExtPrebid rubiconImpExtPrebid = priceFloorResult != null - ? makeRubiconExtPrebid(priceFloorResult, ipfResolvedCurrency, imp, bidRequest) - : null; + ExtRequest extRequest) { final RubiconImpExtRpRtb rubiconImpExtRpRtb = CollectionUtils.isNotEmpty(formats) ? RubiconImpExtRpRtb.of(formats) @@ -702,7 +683,6 @@ private RubiconImpExt makeImpExt(Imp imp, .gpid(getGpid(imp.getExt())) .skadn(getSkadn(imp.getExt())) .tid(getTid(imp.getExt())) - .prebid(rubiconImpExtPrebid) .build(); } @@ -722,30 +702,6 @@ private JsonNode makeTarget(Imp imp, ExtImpRubicon rubiconImpExt, Site site, App return result; } - private RubiconImpExtPrebid makeRubiconExtPrebid(PriceFloorResult priceFloorResult, - String currency, - Imp imp, - BidRequest bidRequest) { - final ObjectNode impExt = imp.getExt(); - final ExtImpPrebid extImpPrebid = extImpPrebid(impExt.get(PREBID_EXT)); - final ExtImpPrebidFloors floors = extImpPrebid != null ? extImpPrebid.getFloors() : null; - - return RubiconImpExtPrebid.of(ExtImpPrebidFloors.of( - priceFloorResult.getFloorRule(), - convertToXAPICurrency(priceFloorResult.getFloorRuleValue(), currency, imp, bidRequest), - convertToXAPICurrency(priceFloorResult.getFloorValue(), currency, imp, bidRequest), - floors != null ? floors.getFloorMin() : null, - floors != null ? floors.getFloorMinCur() : null)); - } - - private ExtImpPrebid extImpPrebid(JsonNode extImpPrebid) { - try { - return mapper.mapper().treeToValue(extImpPrebid, ExtImpPrebid.class); - } catch (JsonProcessingException e) { - throw new PreBidException("Error decoding imp.ext.prebid: " + e.getMessage(), e); - } - } - private void mergeFirstPartyDataFromSite(Site site, ObjectNode result) { // merge OPENRTB.site.ext.data.* to every impression – XAPI.imp[].ext.rp.target.* final ExtSite siteExt = site != null ? site.getExt() : null; diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java index fd6206cb90d..0d626029c9f 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java @@ -61,4 +61,10 @@ public class ExtImpPrebid { * Defines the contract for bidrequest.imp[i].ext.prebid.imp */ ObjectNode imp; + + /** + * Defines the contract for bidrequest.imp[i].ext.prebid.adunitcode + */ + @JsonProperty("adunitcode") + String adUnitCode; } diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/ImpExtPrebid.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/ImpExtPrebid.groovy index fc771e59919..6ff83b53b9c 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/ImpExtPrebid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/ImpExtPrebid.groovy @@ -19,6 +19,9 @@ class ImpExtPrebid { ImpExtPrebidFloors floors Map passThrough Map imp + String adUnitCode + PrebidOptions options + static ImpExtPrebid getDefaultImpExtPrebid() { new ImpExtPrebid().tap { diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy index ba89f5680fa..6a6ae093ea5 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy @@ -29,7 +29,7 @@ class Prebid { List multibid Pbs pbs Server server - Map> bidderParams + Map bidderParams ExtPrebidFloors floors Map passThrough Events events diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/PrebidOptions.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/PrebidOptions.groovy new file mode 100644 index 00000000000..3763eb668aa --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/PrebidOptions.groovy @@ -0,0 +1,12 @@ +package org.prebid.server.functional.model.request.auction + +import com.fasterxml.jackson.databind.PropertyNamingStrategies +import com.fasterxml.jackson.databind.annotation.JsonNaming +import groovy.transform.ToString + +@ToString(includeNames = true, ignoreNulls = true) +@JsonNaming(PropertyNamingStrategies.LowerCaseStrategy) +class PrebidOptions { + + Boolean echoVideoAttrs +} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/PrebidStoredRequest.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/PrebidStoredRequest.groovy index 9f55008332f..024fa9dfac5 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/PrebidStoredRequest.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/PrebidStoredRequest.groovy @@ -1,8 +1,10 @@ package org.prebid.server.functional.model.request.auction +import groovy.transform.EqualsAndHashCode import groovy.transform.ToString @ToString(includeNames = true) +@EqualsAndHashCode class PrebidStoredRequest { String id diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/Prebid.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/Prebid.groovy index e894510811c..35fa5b6a540 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/Prebid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/Prebid.groovy @@ -2,6 +2,7 @@ package org.prebid.server.functional.model.response.auction import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming +import org.prebid.server.functional.model.request.auction.Video @JsonNaming(PropertyNamingStrategies.LowerCaseStrategy) class Prebid { @@ -13,4 +14,5 @@ class Prebid { Events events Meta meta Map passThrough + Video storedRequestAttributes } diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy index cab50bd816b..a9da07cbd6d 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy @@ -16,6 +16,7 @@ import org.prebid.server.functional.model.request.auction.ImpExt import org.prebid.server.functional.model.request.auction.ImpExtContext import org.prebid.server.functional.model.request.auction.ImpExtContextData import org.prebid.server.functional.model.request.auction.Native +import org.prebid.server.functional.model.request.auction.PrebidOptions import org.prebid.server.functional.model.request.auction.PrebidStoredRequest import org.prebid.server.functional.model.request.auction.Site import org.prebid.server.functional.model.request.vtrack.VtrackRequest @@ -69,6 +70,9 @@ class BidderParamsSpec extends BaseSpec { and: "Response should not contain error" assert !response.ext?.errors + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(adapterConfig) + where: adapterDefault | generic | adapterConfig "true" | "true" | ["adapter-defaults.enabled" : adapterDefault, @@ -92,6 +96,9 @@ class BidderParamsSpec extends BaseSpec { then: "Response should contain error" assert response.ext?.errors[GENERIC]*.code == [2] + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(adapterConfig) + where: adapterDefault | generic | adapterConfig "false" | "false" | ["adapter-defaults.enabled": adapterDefault, @@ -103,8 +110,9 @@ class BidderParamsSpec extends BaseSpec { def "PBS should modify vast xml when adapter-defaults.modifying-vast-xml-allowed = #adapterDefault and BIDDER.modifying-vast-xml-allowed = #generic"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService(["adapter-defaults.modifying-vast-xml-allowed": adapterDefault, - "adapters.generic.modifying-vast-xml-allowed": generic]) + def pbsConfig = ["adapter-defaults.modifying-vast-xml-allowed": adapterDefault, + "adapters.generic.modifying-vast-xml-allowed": generic] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default vtrack request" String payload = PBSUtils.randomString @@ -123,6 +131,9 @@ class BidderParamsSpec extends BaseSpec { assert prebidCacheRequest.size() == 1 assert prebidCacheRequest.first().contains("/event?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + where: adapterDefault | generic "true" | "true" @@ -131,8 +142,9 @@ class BidderParamsSpec extends BaseSpec { def "PBS should not modify vast xml when adapter-defaults.modifying-vast-xml-allowed = #adapterDefault and BIDDER.modifying-vast-xml-allowed = #generic"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService(["adapter-defaults.modifying-vast-xml-allowed": adapterDefault, - "adapters.generic.modifying-vast-xml-allowed": generic]) + def pbsConfig = ["adapter-defaults.modifying-vast-xml-allowed": adapterDefault, + "adapters.generic.modifying-vast-xml-allowed": generic] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default VtrackRequest" String payload = PBSUtils.randomString @@ -151,6 +163,9 @@ class BidderParamsSpec extends BaseSpec { assert prebidCacheRequest.size() == 1 assert !prebidCacheRequest.first().contains("/event?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + where: adapterDefault | generic "true" | "false" @@ -159,8 +174,9 @@ class BidderParamsSpec extends BaseSpec { def "PBS should mask values when adapter-defaults.pbs-enforces-ccpa = #adapterDefault settings when BIDDER.pbs-enforces-ccpa = #generic"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService(["adapter-defaults.pbs-enforces-ccpa": adapterDefault, - "adapters.generic.pbs-enforces-ccpa": generic]) + def pbsConfig = ["adapter-defaults.pbs-enforces-ccpa": adapterDefault, + "adapters.generic.pbs-enforces-ccpa": generic] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic generic BidRequest" def bidRequest = BidRequest.defaultBidRequest @@ -178,6 +194,9 @@ class BidderParamsSpec extends BaseSpec { assert bidderRequests.device?.geo?.lat as BigDecimal == PBSUtils.roundDecimal(lat, 2) assert bidderRequests.device?.geo?.lon as BigDecimal == PBSUtils.roundDecimal(lon, 2) + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + where: adapterDefault | generic "true" | "true" @@ -186,8 +205,9 @@ class BidderParamsSpec extends BaseSpec { def "PBS should not mask values when adapter-defaults.pbs-enforces-ccpa = #adapterDefault settings when BIDDER.pbs-enforces-ccpa = #generic"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService(["adapter-defaults.pbs-enforces-ccpa": adapterDefault, - "adapters.generic.pbs-enforces-ccpa": generic]) + def pbsConfig = ["adapter-defaults.pbs-enforces-ccpa": adapterDefault, + "adapters.generic.pbs-enforces-ccpa": generic] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic generic BidRequest" def bidRequest = BidRequest.defaultBidRequest @@ -205,6 +225,9 @@ class BidderParamsSpec extends BaseSpec { assert bidderRequests.device?.geo?.lat == lat assert bidderRequests.device?.geo?.lon == lon + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + where: adapterDefault | generic "true" | "false" @@ -284,9 +307,10 @@ class BidderParamsSpec extends BaseSpec { // TODO: create same test for enabled circuit breaker def "PBS should emit warning when bidder endpoint is invalid"() { given: "Pbs config" - def pbsService = pbsServiceFactory.getService(["adapters.generic.enabled" : "true", - "adapters.generic.endpoint" : "https://", - "http-client.circuit-breaker.enabled": "false"]) + def pbsConfig = ["adapters.generic.enabled" : "true", + "adapters.generic.endpoint" : "https://", + "http-client.circuit-breaker.enabled": "false"] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic generic BidRequest" def bidRequest = BidRequest.defaultBidRequest @@ -297,6 +321,9 @@ class BidderParamsSpec extends BaseSpec { then: "Response should contain error" assert response.ext?.errors[GENERIC]*.code == [999] assert response.ext?.errors[GENERIC]*.message == ["host name must not be empty"] + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should reject bidder when bidder params from request doesn't satisfy json-schema for auction request"() { @@ -390,9 +417,9 @@ class BidderParamsSpec extends BaseSpec { def "PBS should emit error when filter-imp-media-type = true and #configMediaType is empty in bidder config"() { given: "Pbs config" - def pbsService = pbsServiceFactory.getService( - ["auction.filter-imp-media-type.enabled" : "true", - ("adapters.generic.meta-info.${configMediaType}".toString()): ""]) + def pbsConfig = ["auction.filter-imp-media-type.enabled" : "true", + ("adapters.generic.meta-info.${configMediaType}".toString()): ""] + def pbsService = pbsServiceFactory.getService(pbsConfig) when: "PBS processes auction request" def response = pbsService.sendAuctionRequest(bidRequest) @@ -404,6 +431,9 @@ class BidderParamsSpec extends BaseSpec { assert response.ext?.warnings[GENERIC]*.code == [2] assert response.ext?.warnings[GENERIC]*.message == ["Bidder does not support any media types."] + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + where: configMediaType | bidRequest "app-media-types" | BidRequest.getDefaultBidRequest(APP) @@ -412,9 +442,9 @@ class BidderParamsSpec extends BaseSpec { def "PBS should not validate request when filter-imp-media-type = false and #configMediaType is empty in bidder config"() { given: "Pbs config" - def pbsService = pbsServiceFactory.getService( - ["auction.filter-imp-media-type.enabled" : "false", - ("adapters.generic.meta-info.${configMediaType}".toString()): ""]) + def pbsConfig = ["auction.filter-imp-media-type.enabled" : "false", + ("adapters.generic.meta-info.${configMediaType}".toString()): ""] + def pbsService = pbsServiceFactory.getService(pbsConfig) when: "PBS processes auction request" def response = pbsService.sendAuctionRequest(bidRequest) @@ -425,6 +455,9 @@ class BidderParamsSpec extends BaseSpec { and: "Response should not contain error" assert !response.ext?.errors + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + where: configMediaType | bidRequest "app-media-types" | BidRequest.getDefaultBidRequest(APP) @@ -433,9 +466,9 @@ class BidderParamsSpec extends BaseSpec { def "PBS should emit error when filter-imp-media-type = true and request contains media type that is not configured in bidder config"() { given: "Pbs config" - def pbsService = pbsServiceFactory.getService( - ["auction.filter-imp-media-type.enabled" : "true", - "adapters.generic.meta-info.site-media-types": "native"]) + def pbsConfig = ["auction.filter-imp-media-type.enabled" : "true", + "adapters.generic.meta-info.site-media-types": "native"] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic BidRequest with banner, native" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -460,13 +493,16 @@ class BidderParamsSpec extends BaseSpec { and: "Response should not contain warnings" assert !response.ext?.warnings + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should not validate request when filter-imp-media-type = false and request contains only media type that is not configured in bidder config"() { given: "Pbs config" - def pbsService = pbsServiceFactory.getService( - ["auction.filter-imp-media-type.enabled" : "false", - "adapters.generic.meta-info.site-media-types": "native"]) + def pbsConfig = ["auction.filter-imp-media-type.enabled" : "false", + "adapters.generic.meta-info.site-media-types": "native"] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic BidRequest with banner, native" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -485,13 +521,16 @@ class BidderParamsSpec extends BaseSpec { and: "Response should not contain error" assert !response.ext?.errors + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should emit error for request with multiple impressions when filter-imp-media-type = true, one of imp doesn't contain supported media type"() { given: "Pbs config" - def pbsService = pbsServiceFactory.getService( - ["auction.filter-imp-media-type.enabled" : "true", - "adapters.generic.meta-info.site-media-types": "native,video"]) + def pbsConfig = ["auction.filter-imp-media-type.enabled" : "true", + "adapters.generic.meta-info.site-media-types": "native,video"] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic BidRequest with banner, native" def nativeImp = Imp.getDefaultImpression(NATIVE) @@ -525,13 +564,16 @@ class BidderParamsSpec extends BaseSpec { and: "seatbid should not be empty" assert !response.seatbid.isEmpty() + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS auction should reject the bidder with media-type that is not supported by DOOH configuration with proper warning"() { given: "PBS service with configuration for dooh media-types" - def pbsService = pbsServiceFactory.getService( - ["auction.filter-imp-media-type.enabled" : "true", - "adapters.generic.meta-info.dooh-media-types": mediaType]) + def pbsConfig = ["auction.filter-imp-media-type.enabled" : "true", + "adapters.generic.meta-info.dooh-media-types": mediaType] + def pbsService = pbsServiceFactory.getService(pbsConfig) when: "Requesting PBS auction" def bidResponse = pbsService.sendAuctionRequest(bidRequest) @@ -545,6 +587,9 @@ class BidderParamsSpec extends BaseSpec { and: "Should't send any bidder request" assert !bidder.getBidderRequests(bidRequest.id) + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + where: mediaType | bidRequest VIDEO.value | BidRequest.getDefaultBidRequest(DOOH) @@ -556,9 +601,9 @@ class BidderParamsSpec extends BaseSpec { def "PBS auction should reject only imps with media-type that is not supported by DOOH configuration with proper warning"() { given: "PBS service with configuration for dooh media-types" - def pbsService = pbsServiceFactory.getService( - ["auction.filter-imp-media-type.enabled" : "true", - "adapters.generic.meta-info.dooh-media-types": mediaType.value]) + def pbsConfig = ["auction.filter-imp-media-type.enabled" : "true", + "adapters.generic.meta-info.dooh-media-types": mediaType.value] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default bid response with adm and nurl" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { @@ -580,6 +625,9 @@ class BidderParamsSpec extends BaseSpec { and: "Should send bidder request with only proper imp" assert bidder.getBidderRequest(bidRequest.id).imp.id == [bidRequest.imp.first().id] + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + where: mediaType | bidRequest BANNER | BidRequest.getDefaultBidRequest(DOOH).tap { imp << Imp.getDefaultImpression(VIDEO) } @@ -589,9 +637,9 @@ class BidderParamsSpec extends BaseSpec { def "PBS should return empty seatBit when filter-imp-media-type = true, request.imp doesn't contain supported media type"() { given: "Pbs config" - def pbsService = pbsServiceFactory.getService( - ["auction.filter-imp-media-type.enabled" : "true", - "adapters.generic.meta-info.site-media-types": "native,video"]) + def pbsConfig = ["auction.filter-imp-media-type.enabled" : "true", + "adapters.generic.meta-info.site-media-types": "native,video"] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic BidRequest with banner" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -614,6 +662,9 @@ class BidderParamsSpec extends BaseSpec { and: "seatbid should be empty" assert response.seatbid.isEmpty() + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should send server specific info to bidder when such is set in PBS config"() { @@ -621,9 +672,10 @@ class BidderParamsSpec extends BaseSpec { def serverDataCenter = PBSUtils.randomString def serverExternalUrl = "https://${PBSUtils.randomString}.com/" def serverHostVendorId = PBSUtils.randomNumber - def pbsService = pbsServiceFactory.getService(["datacenter-region" : serverDataCenter, - "external-url" : serverExternalUrl as String, - "gdpr.host-vendor-id": serverHostVendorId as String]) + def pbsConfig = ["datacenter-region" : serverDataCenter, + "external-url" : serverExternalUrl as String, + "gdpr.host-vendor-id": serverHostVendorId as String] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Bid request" def bidRequest = BidRequest.defaultBidRequest @@ -637,13 +689,17 @@ class BidderParamsSpec extends BaseSpec { assert bidderRequest?.ext?.prebid?.server?.externalUrl == serverExternalUrl assert bidderRequest.ext.prebid.server.datacenter == serverDataCenter assert bidderRequest.ext.prebid.server.gvlId == serverHostVendorId + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should request to bidder with header Content-Encoding = gzip when adapters.BIDDER.endpoint-compression = gzip"() { given: "PBS with adapter configuration" def compressionType = GZIP.value - def pbsService = pbsServiceFactory.getService(["adapters.generic.enabled" : "true", - "adapters.generic.endpoint-compression": compressionType]) + def pbsConfig = ["adapters.generic.enabled" : "true", + "adapters.generic.endpoint-compression": compressionType] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default bid request" def bidRequest = BidRequest.defaultBidRequest @@ -654,12 +710,16 @@ class BidderParamsSpec extends BaseSpec { then: "Bidder request should contain header Content-Encoding = gzip" assert response.ext?.debug?.httpcalls?.get(BidderName.GENERIC.value)?.requestHeaders?.first() ?.get(CONTENT_ENCODING_HEADER)?.first() == compressionType + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should send request to bidder without header Content-Encoding when adapters.BIDDER.endpoint-compression = none"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService(["adapters.generic.enabled" : "true", - "adapters.generic.endpoint-compression": NONE.value]) + def pbsConfig = ["adapters.generic.enabled" : "true", + "adapters.generic.endpoint-compression": NONE.value] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default bid request" def bidRequest = BidRequest.defaultBidRequest @@ -670,6 +730,9 @@ class BidderParamsSpec extends BaseSpec { then: "Bidder request should not contain header Content-Encoding" assert !response.ext?.debug?.httpcalls?.get(BidderName.GENERIC.value)?.requestHeaders?.first() ?.get(CONTENT_ENCODING_HEADER) + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should not treat reserved imp[].ext.tid object as a bidder"() { @@ -776,10 +839,32 @@ class BidderParamsSpec extends BaseSpec { "request.imp[0].ext.prebid.bidder contains unknown bidder: anyUnsupportedBidder"] } + def "PBS should emit warning and proceed auction when ext.prebid fields include adunitcode"() { + given: "Default bid request with populated ext.prebid.bidderParams" + def genericBidderParams = PBSUtils.randomString + def bidRequest = BidRequest.defaultBidRequest.tap { + ext.prebid.bidderParams = [adUnitCode : PBSUtils.randomString, + (GENERIC.value): genericBidderParams] + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response shouldn't contain error" + assert !response.ext?.errors + + and: "PBS should emit an warning" + assert response?.ext?.warnings[PREBID]*.code == [999] + assert response?.ext?.warnings[PREBID]*.message == + ["WARNING: request.imp[0].ext.prebid.bidder.adUnitCode was dropped with a reason: " + + "request.imp[0].ext.prebid.bidder contains unknown bidder: adUnitCode"] + } + def "PBS shouldn't emit warning and proceed auction when all imp.ext fields known for PBS"() { given: "Default bid request with populated imp.ext" def impExt = ImpExt.getDefaultImpExt().tap { prebid.bidder.generic = null + prebid.adUnitCode = PBSUtils.randomString generic = new Generic() ae = PBSUtils.randomNumber all = PBSUtils.randomNumber @@ -795,9 +880,15 @@ class BidderParamsSpec extends BaseSpec { } when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response shouldn't contain error" + assert !response.ext?.errors + + and: "Response shouldn't contain warning" + assert !response.ext?.warnings - then: "Bidder request should contain same field as requested" + and: "Bidder request should contain same field as requested" def bidderRequest = bidder.getBidderRequest(bidRequest.id) verifyAll(bidderRequest.imp[0].ext) { bidder == impExt.generic @@ -809,12 +900,91 @@ class BidderParamsSpec extends BaseSpec { gpid == impExt.gpid skadn == impExt.skadn tid == impExt.tid + prebid.adUnitCode == impExt.prebid.adUnitCode + } + } + + def "PBS shouldn't emit warning and proceed auction when all imp.ext.prebid fields known for PBS"() { + given: "PBS with old ortb version" + def pbsConfig = ['adapters.generic.ortb-version': '2.5'] + def pbsService = pbsServiceFactory.getService(pbsConfig) + + and: "Default bid request with populated imp.ext.prebid" + def impExt = ImpExt.getDefaultImpExt().tap { + prebid.adUnitCode = PBSUtils.randomString + prebid.storedRequest = new PrebidStoredRequest(id: PBSUtils.randomString) + prebid.isRewardedInventory = PBSUtils.getRandomNumber(0, 1) + prebid.options = new PrebidOptions(echoVideoAttrs: PBSUtils.randomBoolean) + } + def bidRequest = BidRequest.defaultVideoRequest.tap { + imp[0].rwdd = null + imp[0].ext = impExt + } + + and: "Save storedImp into DB" + def storedImp = StoredImp.getStoredImp(bidRequest) + storedImpDao.save(storedImp) + + and: "Default bid response" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Response shouldn't contain error" + assert !response.ext?.errors + + and: "Response shouldn't contain warning" + assert !response.ext?.warnings + + and: "Bidder request should contain same field as requested" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + verifyAll(bidderRequest.imp[0].ext.prebid) { + it.adUnitCode == impExt.prebid.adUnitCode + it.storedRequest == impExt.prebid.storedRequest + it.isRewardedInventory == impExt.prebid.isRewardedInventory + it.options.echoVideoAttrs == impExt.prebid.options.echoVideoAttrs } + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + } + + def "PBS should proceed auction without warning when all ext.prebid.bidderParams fields are known"() { + given: "Default bid request with populated ext.prebid.bidderParams" + def genericBidderParams = PBSUtils.randomString + def bidRequest = BidRequest.defaultBidRequest.tap { + ext.prebid.bidderParams = [ae : PBSUtils.randomString, + all : PBSUtils.randomString, + context : PBSUtils.randomString, + data : PBSUtils.randomString, + general : PBSUtils.randomString, + gpid : PBSUtils.randomString, + skadn : PBSUtils.randomString, + tid : PBSUtils.randomString, + (GENERIC.value): genericBidderParams + ] + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response shouldn't contain error" + assert !response.ext?.errors + + and: "Response shouldn't contain warning" + assert !response.ext?.warnings + + and: "Bidder request should bidderParams only for bidder" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.ext.prebid.bidderParams == [(GENERIC.value): genericBidderParams] } def "PBS should send request to bidder when adapters.bidder.meta-info.currency-accepted not specified"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService("adapters.generic.meta-info.currency-accepted": "") + def pbsConfig = ['adapters.generic.meta-info.currency-accepted': ''] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default bid request with generic bidder" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -842,14 +1012,17 @@ class BidderParamsSpec extends BaseSpec { and: "PBS response shouldn't contain seatNonBid" assert !response.ext.seatnonbid + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should send request to bidder when adapters.bidder.aliases.bidder.meta-info.currency-accepted not specified"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService( - "adapters.generic.aliases.alias.enabled" : "true", - "adapters.generic.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString(), - "adapters.generic.aliases.alias.meta-info.currency-accepted": "") + def pbsConfig = ["adapters.generic.aliases.alias.enabled": "true", + "adapters.generic.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString(), + "adapters.generic.aliases.alias.meta-info.currency-accepted": ""] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default bid request with alias bidder" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -879,11 +1052,15 @@ class BidderParamsSpec extends BaseSpec { and: "PBS response shouldn't contain seatNonBid" assert !response.ext.seatnonbid + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should send request to bidder when adapters.bidder.meta-info.currency-accepted intersect with requested currency"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService("adapters.generic.meta-info.currency-accepted": "${USD},${EUR}".toString()) + def pbsConfig = ["adapters.generic.meta-info.currency-accepted": "${USD},${EUR}".toString()] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic generic BidRequest" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -911,11 +1088,15 @@ class BidderParamsSpec extends BaseSpec { and: "PBS response shouldn't contain seatNonBid and contain errors" assert !response.ext.seatnonbid + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS shouldn't send request to bidder and emit warning when adapters.bidder.meta-info.currency-accepted not intersect with requested currency"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService("adapters.generic.meta-info.currency-accepted": "${JPY},${CHF}".toString()) + def pbsConfig = ["adapters.generic.meta-info.currency-accepted": "${JPY},${CHF}".toString()] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic generic BidRequest" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -950,14 +1131,17 @@ class BidderParamsSpec extends BaseSpec { assert seatNonBid.seat == BidderName.GENERIC.value assert seatNonBid.nonBid[0].impId == bidRequest.imp[0].id assert seatNonBid.nonBid[0].statusCode == REQUEST_BLOCKED_UNACCEPTABLE_CURRENCY + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS should send request to bidder when adapters.bidder.aliases.bidder.meta-info.currency-accepted intersect with requested currency"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService( - "adapters.generic.aliases.alias.enabled" : "true", - "adapters.generic.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString(), - "adapters.generic.aliases.alias.meta-info.currency-accepted": "${USD},${EUR}".toString()) + def pbsConfig = ["adapters.generic.aliases.alias.enabled": "true", + "adapters.generic.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString(), + "adapters.generic.aliases.alias.meta-info.currency-accepted": "${USD},${EUR}".toString()] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic BidRequest with alias bidder" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -991,14 +1175,17 @@ class BidderParamsSpec extends BaseSpec { and: "PBS response shouldn't contain seatNonBid and contain errors" assert !response.ext.seatnonbid + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } def "PBS shouldn't send request to bidder and emit warning when adapters.bidder.aliases.bidder.meta-info.currency-accepted not intersect with requested currency"() { given: "PBS with adapter configuration" - def pbsService = pbsServiceFactory.getService( - "adapters.generic.aliases.alias.enabled" : "true", - "adapters.generic.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString(), - "adapters.generic.aliases.alias.meta-info.currency-accepted": "${JPY},${CHF}".toString()) + def pbsConfig = ["adapters.generic.aliases.alias.enabled": "true", + "adapters.generic.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString(), + "adapters.generic.aliases.alias.meta-info.currency-accepted": "${JPY},${CHF}".toString()] + def pbsService = pbsServiceFactory.getService(pbsConfig) and: "Default basic BidRequest with alias bidder" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -1039,5 +1226,8 @@ class BidderParamsSpec extends BaseSpec { assert seatNonBid.seat == BidderName.ALIAS.value assert seatNonBid.nonBid[0].impId == bidRequest.imp[0].id assert seatNonBid.nonBid[0].statusCode == REQUEST_BLOCKED_UNACCEPTABLE_CURRENCY + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsCurrencySpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsCurrencySpec.groovy index 786a70a6b86..69d8dce297d 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsCurrencySpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsCurrencySpec.groovy @@ -417,12 +417,14 @@ class PriceFloorsCurrencySpec extends PriceFloorsBaseSpec { currencyFloorsPbsService.sendAuctionRequest(bidRequest) then: "Bidder request should contain floorMin, floorMinCur, currency from request" - verifyAll(bidder.getBidderRequest(bidRequest.id)) { - imp[0].ext.prebid.floors.floorMinCur == EUR - imp[0].ext.prebid.floors.floorMin == FLOOR_MIN + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + verifyAll(bidderRequest) { ext.prebid.floors.floorMinCur == EUR ext.prebid.floors.floorMin == FLOOR_MIN } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should return warning when both floorMinCur and floorMinCur exist and they're different"() { @@ -445,12 +447,14 @@ class PriceFloorsCurrencySpec extends PriceFloorsBaseSpec { ["imp[].ext.prebid.floors.floorMinCur and ext.prebid.floors.floorMinCur has different values"] and: "Bidder request should contain floorMinCur, floorMin from request" - verifyAll(bidder.getBidderRequest(bidRequest.id)) { - imp[0].ext.prebid.floors.floorMinCur == EUR - imp[0].ext.prebid.floors.floorMin == FLOOR_MIN + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + verifyAll(bidderRequest) { ext.prebid.floors.floorMinCur == JPY ext.prebid.floors.floorMin == FLOOR_MIN } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should choose floorMin from imp[0].ext.prebid.floors when imp[0].ext.prebid.floors is present"() { @@ -470,13 +474,14 @@ class PriceFloorsCurrencySpec extends PriceFloorsBaseSpec { currencyFloorsPbsService.sendAuctionRequest(bidRequest) then: "Bidder request should contain floorMin, floorValue, bidFloor, bidFloorCur" - verifyAll(bidder.getBidderRequest(bidRequest.id)) { - imp[0].ext.prebid.floors.floorMinCur == USD - imp[0].ext.prebid.floors.floorMin == impExtPrebidFloorMin - imp[0].ext.prebid.floors.floorValue == impExtPrebidFloorMin + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + verifyAll(bidderRequest) { imp[0].bidFloor == impExtPrebidFloorMin imp[0].bidFloorCur == USD } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should choose floorMin from ext.prebid.floors when imp[0].ext.prebid.floor.floorMin is absent"() { @@ -495,12 +500,13 @@ class PriceFloorsCurrencySpec extends PriceFloorsBaseSpec { currencyFloorsPbsService.sendAuctionRequest(bidRequest) then: "Bidder request should contain bidFloorCur, bidFloor, floorValue" - verifyAll(bidder.getBidderRequest(bidRequest.id)) { - !imp[0].ext.prebid.floors.floorMinCur - !imp[0].ext.prebid.floors.floorMin - imp[0].ext.prebid.floors.floorValue == extPrebidFloorMin + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + verifyAll(bidderRequest) { imp[0].bidFloor == extPrebidFloorMin imp[0].bidFloorCur == USD } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsFetchingSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsFetchingSpec.groovy index 55180fe60d4..a897fbeff7c 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsFetchingSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsFetchingSpec.groovy @@ -418,10 +418,6 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { imp[0].bidFloor == floorValue imp[0].bidFloorCur == floorsResponse.modelGroups[0].currency - imp[0].ext?.prebid?.floors?.floorRule == floorsResponse.modelGroups[0].values.keySet()[0] - imp[0].ext?.prebid?.floors?.floorRuleValue == floorValue - imp[0].ext?.prebid?.floors?.floorValue == floorValue - ext?.prebid?.floors?.location == FETCH ext?.prebid?.floors?.fetchStatus == SUCCESS ext?.prebid?.floors?.floorProvider == floorsResponse.floorProvider @@ -429,6 +425,9 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { ext?.prebid?.floors?.skipRate == floorsResponse.skipRate ext?.prebid?.floors?.data == floorsResponse } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS shouldn't fetch data from provider when use-dynamic-data disabled and useFetchDataRate at max value"() { @@ -999,13 +998,6 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { imp[0].bidFloor == storedRequestModel.ext.prebid.floors.data.modelGroups[0].values[rule] imp[0].bidFloorCur == storedRequestModel.ext.prebid.floors.data.modelGroups[0].currency - imp[0].ext?.prebid?.floors?.floorRule == - storedRequestModel.ext.prebid.floors.data.modelGroups[0].values.keySet()[0] - imp[0].ext?.prebid?.floors?.floorRuleValue == - storedRequestModel.ext.prebid.floors.data.modelGroups[0].values[rule] - imp[0].ext?.prebid?.floors?.floorValue == - storedRequestModel.ext.prebid.floors.data.modelGroups[0].values[rule] - ext?.prebid?.floors?.location == REQUEST ext?.prebid?.floors?.fetchStatus == NONE ext?.prebid?.floors?.floorMin == storedRequestModel.ext.prebid.floors.floorMin @@ -1013,6 +1005,9 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { ext?.prebid?.floors?.data == storedRequestModel.ext.prebid.floors.data } + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors + where: request | bidRequestWithFloors BidRequest.defaultBidRequest | getBidRequestWithFloors(SITE) @@ -1044,16 +1039,15 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { imp[0].bidFloor == bidRequest.ext.prebid.floors.data.modelGroups[0].values[rule] imp[0].bidFloorCur == bidRequest.ext.prebid.floors.data.modelGroups[0].currency - imp[0].ext?.prebid?.floors?.floorRule == bidRequest.ext.prebid.floors.data.modelGroups[0].values.keySet()[0] - imp[0].ext?.prebid?.floors?.floorRuleValue == bidRequest.ext.prebid.floors.data.modelGroups[0].values[rule] - imp[0].ext?.prebid?.floors?.floorValue == bidRequest.ext.prebid.floors.data.modelGroups[0].values[rule] - ext?.prebid?.floors?.location == REQUEST ext?.prebid?.floors?.fetchStatus == NONE ext?.prebid?.floors?.floorMin == bidRequest.ext.prebid.floors.floorMin ext?.prebid?.floors?.floorProvider == bidRequest.ext.prebid.floors.data.floorProvider ext?.prebid?.floors?.data == bidRequest.ext.prebid.floors.data } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should prefer data from stored request when fetch is disabled in account config for amp request"() { @@ -1080,19 +1074,15 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { imp[0].bidFloor == ampStoredRequest.ext.prebid.floors.data.modelGroups[0].values[rule] imp[0].bidFloorCur == ampStoredRequest.ext.prebid.floors.data.modelGroups[0].currency - imp[0].ext?.prebid?.floors?.floorRule == - ampStoredRequest.ext.prebid.floors.data.modelGroups[0].values.keySet()[0] - imp[0].ext?.prebid?.floors?.floorRuleValue == - ampStoredRequest.ext.prebid.floors.data.modelGroups[0].values[rule] - imp[0].ext?.prebid?.floors?.floorValue == - ampStoredRequest.ext.prebid.floors.data.modelGroups[0].values[rule] - ext?.prebid?.floors?.location == REQUEST ext?.prebid?.floors?.fetchStatus == NONE ext?.prebid?.floors?.floorMin == ampStoredRequest.ext.prebid.floors.floorMin ext?.prebid?.floors?.floorProvider == ampStoredRequest.ext.prebid.floors.data.floorProvider ext?.prebid?.floors?.data == ampStoredRequest.ext.prebid.floors.data } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should prefer data from floors provider when floors data is defined in both request and stored request"() { @@ -1130,10 +1120,6 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { imp[0].bidFloor == floorValue imp[0].bidFloorCur == floorsResponse.modelGroups[0].currency - imp[0].ext?.prebid?.floors?.floorRule == floorsResponse.modelGroups[0].values.keySet()[0] - imp[0].ext?.prebid?.floors?.floorRuleValue == floorValue - imp[0].ext?.prebid?.floors?.floorValue == floorValue - ext?.prebid?.floors?.location == FETCH ext?.prebid?.floors?.fetchStatus == SUCCESS ext?.prebid?.floors?.floorMin == bidRequest.ext.prebid.floors.floorMin @@ -1142,6 +1128,9 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { ext?.prebid?.floors?.skipRate == floorsResponse.skipRate ext?.prebid?.floors?.data == floorsResponse } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should prefer data from floors provider when floors data is defined in stored request for amp request"() { @@ -1175,10 +1164,6 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { imp[0].bidFloor == floorValue imp[0].bidFloorCur == floorsResponse.modelGroups[0].currency - imp[0].ext?.prebid?.floors?.floorRule == floorsResponse.modelGroups[0].values.keySet()[0] - imp[0].ext?.prebid?.floors?.floorRuleValue == floorValue - imp[0].ext?.prebid?.floors?.floorValue == floorValue - ext?.prebid?.floors?.location == FETCH ext?.prebid?.floors?.fetchStatus == SUCCESS ext?.prebid?.floors?.floorMin == ampStoredRequest.ext.prebid.floors.floorMin @@ -1187,6 +1172,9 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { ext?.prebid?.floors?.skipRate == floorsResponse.skipRate ext?.prebid?.floors?.data == floorsResponse } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should periodically fetch floor rules when previous response from floors provider is #description"() { @@ -1260,9 +1248,6 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { verifyAll(bidderRequest) { imp[0].bidFloor == floorValue imp[0].bidFloorCur == floorsResponse.modelGroups[0].currency - imp[0].ext?.prebid?.floors?.floorRule == floorsResponse.modelGroups[0].values.keySet()[0] - imp[0].ext?.prebid?.floors?.floorRuleValue == floorValue - imp[0].ext?.prebid?.floors?.floorValue == floorValue ext?.prebid?.floors?.location == FETCH ext?.prebid?.floors?.fetchStatus == SUCCESS @@ -1272,6 +1257,9 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { ext?.prebid?.floors?.skipRate == floorsResponse.skipRate ext?.prebid?.floors?.data == floorsResponse } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should validate rules from request when floorMin from request is invalid"() { @@ -1622,9 +1610,6 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { verifyAll(bidderRequest) { imp[0].bidFloor == floorValue imp[0].bidFloorCur == floorsResponse.modelGroups[0].currency - imp[0].ext?.prebid?.floors?.floorRule == floorsResponse.modelGroups[0].values.keySet()[0] - imp[0].ext?.prebid?.floors?.floorRuleValue == floorValue - imp[0].ext?.prebid?.floors?.floorValue == floorValue ext?.prebid?.floors?.location == FETCH ext?.prebid?.floors?.fetchStatus == SUCCESS @@ -1634,6 +1619,9 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { ext?.prebid?.floors?.skipRate == floorsResponse.skipRate ext?.prebid?.floors?.data == floorsResponse } + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should reject fetch when modelWeight from floors provider is invalid"() { 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 d10f6b07b1b..e493bbb7df9 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 @@ -88,8 +88,9 @@ class PriceFloorsRulesSpec extends PriceFloorsBaseSpec { then: "Bidder request bidFloor should correspond to appropriate rule" def bidderRequest = bidder.getBidderRequests(bidRequest.id).last() assert bidderRequest.imp[0].bidFloor == floorValue - assert bidderRequest.imp[0].ext.prebid.floors.floorRule == rule - assert bidderRequest.imp[0].ext.prebid.floors.floorRuleValue == floorValue + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should support different delimiters for floor rules"() { diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsSignalingSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsSignalingSpec.groovy index f1385b1649d..72be2f0a0f3 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsSignalingSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsSignalingSpec.groovy @@ -360,11 +360,10 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "Bidder request bidFloor should be update according to bidAdjustment" def bidderRequest = bidder.getBidderRequests(bidRequest.id).last() - verifyAll(bidderRequest) { - imp[0].bidFloor == floorsProviderFloorValue / bidAdjustment - imp[0].ext.prebid.floors.floorRuleValue == floorsProviderFloorValue - imp[0].ext.prebid.floors.floorValue == imp[0].bidFloor - } + assert bidderRequest.imp[0].bidFloor == floorsProviderFloorValue / bidAdjustment + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors where: pbsConfigBidAdjustmentFlag | requestBidAdjustmentFlag | accountBidAdjustmentFlag @@ -412,8 +411,9 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "Bidder request bidFloor should be changed" def bidderRequest = bidder.getBidderRequests(bidRequest.id).last() assert bidderRequest.imp[0].bidFloor == floorsProviderFloorValue - assert bidderRequest.imp[0].ext.prebid.floors.floorRuleValue == floorsProviderFloorValue - assert bidderRequest.imp[0].ext.prebid.floors.floorValue == floorsProviderFloorValue + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors where: pbsConfigBidAdjustmentFlagSnakeCase | pbsConfigBidAdjustmentFlag | requestBidAdjustmentFlag | accountBidAdjustmentFlag | accountBidAdjustmentFlagSnakeCase @@ -454,8 +454,9 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "Bidder request bidFloor should be update according to bidAdjustment" def bidderRequest = bidder.getBidderRequests(bidRequest.id).last() assert bidderRequest.imp[0].bidFloor == getAdjustedValue(floorValue, bidAdjustment) - assert bidderRequest.imp[0].ext.prebid.floors.floorRuleValue == floorValue - assert bidderRequest.imp[0].ext.prebid.floors.floorValue == bidderRequest.imp[0].bidFloor + + and: "Bidder request shouldn't include imp.ext.prebid.floors" + assert !bidderRequest.imp[0].ext.prebid.floors } def "PBS should remove non-selected models"() { diff --git a/src/test/groovy/org/prebid/server/functional/util/PBSUtils.groovy b/src/test/groovy/org/prebid/server/functional/util/PBSUtils.groovy index 9ac2c148b5b..c82e96268c6 100644 --- a/src/test/groovy/org/prebid/server/functional/util/PBSUtils.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/PBSUtils.groovy @@ -50,6 +50,10 @@ class PBSUtils implements ObjectMapperWrapper { RandomStringUtils.randomAlphanumeric(stringLength) } + static Boolean getRandomBoolean() { + new Random().nextBoolean() + } + static T getRandomElement(List list) { list[getRandomNumber(0, list.size() - 1)] } diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index 11346bc5957..72ea7a78bbe 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -523,7 +523,7 @@ public void shouldExtractRequestWithCurrencyRatesExtension() { // given givenBidder(givenEmptySeatBid()); - final Map> currencyRates = doubleMap( + final Map> currencyRates = Map.of( "GBP", singletonMap("EUR", BigDecimal.valueOf(1.15)), "UAH", singletonMap("EUR", BigDecimal.valueOf(1.1565))); @@ -571,7 +571,7 @@ public void shouldExtractMultipleRequests() { givenBidder("bidder2", bidder2, givenEmptySeatBid()); final BidRequest bidRequest = givenBidRequest(asList( - givenImp(doubleMap("bidder1", 1, "bidder2", 2), identity()), + givenImp(Map.of("bidder1", 1, "bidder2", 2), identity()), givenImp(singletonMap("bidder1", 3), identity()))); // when @@ -1145,7 +1145,7 @@ public void shouldExtractMultipleRequestsForTheSameBidderIfAliasesWereUsed() { givenBidder("bidder", bidder, givenEmptySeatBid()); final BidRequest bidRequest = givenBidRequest(singletonList( - givenImp(doubleMap("bidder", 1, "bidderAlias", 2), identity())), + givenImp(Map.of("bidder", 1, "bidderAlias", 2), identity())), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .aliases(singletonMap("bidderAlias", "bidder")) .auctiontimestamp(1000L) @@ -1175,7 +1175,7 @@ public void shouldExtractMultipleRequestsForBidderAndItsHardcodedAlias() { givenBidder("bidderAlias", bidderAlias, givenEmptySeatBid()); final BidRequest bidRequest = givenBidRequest(singletonList( - givenImp(doubleMap("bidder", 1, "bidderAlias", 2), identity())), + givenImp(Map.of("bidder", 1, "bidderAlias", 2), identity())), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .aliases(singletonMap("bidderAlias", "bidder")) .auctiontimestamp(1000L) @@ -1263,7 +1263,7 @@ public void shouldReturnSeparateSeatBidsForTheSameBidderIfBiddersAliasAndBidderW givenBidderBid(Bid.builder().impid("1").price(BigDecimal.ONE).build()))))); final BidRequest bidRequest = givenBidRequest( - givenSingleImp("1", doubleMap("bidder", 1, "bidderAlias", 2)), + givenSingleImp("1", Map.of("bidder", 1, "bidderAlias", 2)), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .aliases(singletonMap("bidderAlias", "bidder")) .auctiontimestamp(1000L) @@ -1301,7 +1301,7 @@ public void shouldPropagateFledgeResponseWithBidderAlias() { singletonList(Imp.builder() .id("impId") .ext(mapper.valueToTree( - doubleMap("prebid", singletonMap("bidder", singletonMap("bidderAlias", 1)), + Map.of("prebid", singletonMap("bidder", singletonMap("bidderAlias", 1)), "ae", 1))) .build()), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() @@ -1499,7 +1499,7 @@ public void shouldCallBidResponseCreatorWithExpectedParamsAndUpdateDebugErrors() final BidRequest bidRequest = givenBidRequest(asList( // imp ids are not really used for matching, included them here for clarity givenImp(singletonMap("bidder1", 1), builder -> builder.id("impId1")), - givenImp(doubleMap("bidder1", 1, "bidder2", 2), builder -> builder.id("impId2"))), + givenImp(Map.of("bidder1", 1, "bidder2", 2), builder -> builder.id("impId2"))), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .targeting(targeting) .auctiontimestamp(1000L) @@ -1594,7 +1594,7 @@ public void shouldCallBidResponseCreatorWithWinningOnlyTrueWhenIncludeBidderKeys final BidRequest bidRequest = givenBidRequest(asList( // imp ids are not really used for matching, included them here for clarity givenImp(singletonMap("bidder1", 1), builder -> builder.id("impId1")), - givenImp(doubleMap("bidder1", 1, "bidder2", 2), builder -> builder.id("impId2"))), + givenImp(Map.of("bidder1", 1, "bidder2", 2), builder -> builder.id("impId2"))), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .targeting(targeting) .cache(ExtRequestPrebidCache.of(null, null, true)) @@ -1633,7 +1633,7 @@ public void shouldCallBidResponseCreatorWithWinningOnlyFalseWhenWinningOnlyIsNul final BidRequest bidRequest = givenBidRequest(asList( // imp ids are not really used for matching, included them here for clarity givenImp(singletonMap("bidder1", 1), builder -> builder.id("impId1")), - givenImp(doubleMap("bidder1", 1, "bidder2", 2), builder -> builder.id("impId2"))), + givenImp(Map.of("bidder1", 1, "bidder2", 2), builder -> builder.id("impId2"))), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .targeting(targeting) .cache(ExtRequestPrebidCache.of(null, null, null)) @@ -1768,7 +1768,7 @@ public void shouldProcessBidderResponseReturnedFromStoredResponseProcessor() { givenBidder(givenEmptySeatBid()); final BidRequest bidRequest = givenBidRequest(singletonList( - givenImp(doubleMap("prebid", 0, "someBidder", 1), builder -> builder + givenImp(Map.of("prebid", 0, "someBidder", 1), builder -> builder .id("impId") .banner(Banner.builder() .format(singletonList(Format.builder().w(400).h(300).build())) @@ -1802,7 +1802,7 @@ public void shouldReturnFailedFutureWhenStoredResponseProcessorGetStoredResultRe .willReturn(Future.failedFuture(new InvalidRequestException("Error"))); final BidRequest bidRequest = givenBidRequest(singletonList( - givenImp(doubleMap("prebid", 0, "someBidder", 1), builder -> builder + givenImp(Map.of("prebid", 0, "someBidder", 1), builder -> builder .id("impId") .banner(Banner.builder() .format(singletonList(Format.builder().w(400).h(300).build())) @@ -1826,7 +1826,7 @@ public void shouldReturnFailedFutureWhenStoredResponseProcessorMergeBidderRespon .willThrow(new PreBidException("Error")); final BidRequest bidRequest = givenBidRequest(singletonList( - givenImp(doubleMap("prebid", 0, "someBidder", 1), builder -> builder + givenImp(Map.of("prebid", 0, "someBidder", 1), builder -> builder .id("impId") .banner(Banner.builder() .format(singletonList(Format.builder().w(400).h(300).build())) @@ -2123,7 +2123,7 @@ public void shouldPassUserDataAndExtDataOnlyForAllowedBidder() { givenBidder("missingBidder", bidder, givenEmptySeatBid()); final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); - final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); + final Map bidderToGdpr = Map.of("someBidder", 1, "missingBidder", 0); final List eids = singletonList(Eid.builder().source("eId").uids(emptyList()).build()); final ExtUser extUser = ExtUser.builder().data(dataNode).build(); final List data = singletonList(Data.builder().build()); @@ -2363,7 +2363,7 @@ public void shouldMaskUserExtIfDataBiddersListIsEmpty() { givenBidder("missingBidder", bidder, givenEmptySeatBid()); final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); - final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); + final Map bidderToGdpr = Map.of("someBidder", 1, "missingBidder", 0); final List eids = singletonList(Eid.builder().source("eId").uids(emptyList()).build()); final ExtUser extUser = ExtUser.builder().data(dataNode).build(); @@ -2406,7 +2406,7 @@ public void shouldNoMaskUserExtIfDataBiddersListIsNull() { givenBidder("missingBidder", bidder, givenEmptySeatBid()); final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); - final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); + final Map bidderToGdpr = Map.of("someBidder", 1, "missingBidder", 0); final BidRequest bidRequest = givenBidRequest(givenSingleImp(bidderToGdpr), builder -> builder @@ -2449,7 +2449,7 @@ public void shouldPassSiteContentDataAndExtDataOnlyForAllowedBidder() { givenBidder("missingBidder", bidder, givenEmptySeatBid()); final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); - final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); + final Map bidderToGdpr = Map.of("someBidder", 1, "missingBidder", 0); final Content content = Content.builder() .data(singletonList(Data.builder().build())) .album("album") @@ -2502,7 +2502,7 @@ public void shouldPassDoohContentDataAndExtDataOnlyForAllowedBidder() { givenBidder("missingBidder", bidder, givenEmptySeatBid()); final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); - final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); + final Map bidderToGdpr = Map.of("someBidder", 1, "missingBidder", 0); final Content content = Content.builder() .data(singletonList(Data.builder().build())) .album("album") @@ -2553,7 +2553,7 @@ public void shouldPassAppContentDataAndExtDataOnlyForAllowedBidder() { givenBidder("missingBidder", bidder, givenEmptySeatBid()); final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); - final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); + final Map bidderToGdpr = Map.of("someBidder", 1, "missingBidder", 0); final Content content = Content.builder() .data(singletonList(Data.builder().build())) .album("album") @@ -2604,7 +2604,7 @@ public void shouldNoMaskPassAppExtAndKeywordsWhenDataBiddersListIsNull() { givenBidder("missingBidder", bidder, givenEmptySeatBid()); final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); - final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); + final Map bidderToGdpr = Map.of("someBidder", 1, "missingBidder", 0); final BidRequest bidRequest = givenBidRequest(givenSingleImp(bidderToGdpr), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() @@ -2641,7 +2641,7 @@ public void shouldNoMaskPassDoohExtAndKeywordsWhenDataBiddersListIsNull() { givenBidder("missingBidder", bidder, givenEmptySeatBid()); final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); - final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); + final Map bidderToGdpr = Map.of("someBidder", 1, "missingBidder", 0); final BidRequest bidRequest = givenBidRequest(givenSingleImp(bidderToGdpr), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() @@ -3631,13 +3631,22 @@ public void shouldReturnBidResponseWithWarningWhenAnalyticsTagsDisabledAndReques } @Test - public void shouldProperPopulateImpExtPrebidEvenIfInExtImpPrebidContainNotCorrectField() { + public void shouldProperPopulateImpExtPrebid() { // given - final Imp imp = Imp.builder() - .ext(mapper.valueToTree(Map.of("prebid", - doubleMap("test-field", "test-value", "bidder", - Map.of("bidderName", doubleMap("test-host", "unknownHost", "publisher_id", "ps4")))))) - .build(); + final HashMap impExpPrebidMap = new HashMap<>(); + impExpPrebidMap.put("test-field", "test-value"); + impExpPrebidMap.put("storedrequest", Map.of("id", "id")); + impExpPrebidMap.put("options", Map.of("echovideoattrs", true)); + impExpPrebidMap.put("is_rewarded_inventory", 1); + impExpPrebidMap.put("floors", Map.of("floorRule", "rule")); + impExpPrebidMap.put("adunitcode", "adCodeValue"); + impExpPrebidMap.put("passthrough", Map.of("test-field", "test-value")); + impExpPrebidMap.put("storedauctionresponse", Map.of("id", "id")); + impExpPrebidMap.put("bidder", Map.of("bidderName", + Map.of("test-host", "unknownHost", "publisher_id", "ps4"))); + impExpPrebidMap.put("imp", Map.of("test-field", "test-value")); + + final Imp imp = Imp.builder().ext(mapper.valueToTree(Map.of("prebid", impExpPrebidMap))).build(); final BidRequest bidRequest = givenBidRequest(singletonList(imp), identity()); final AuctionContext auctionContext = givenRequestContext(bidRequest); @@ -3653,41 +3662,13 @@ public void shouldProperPopulateImpExtPrebidEvenIfInExtImpPrebidContainNotCorrec final BidRequest capturedBidRequest = captureBidRequest(); assertThat(capturedBidRequest.getImp()) .extracting(Imp::getExt) - .containsExactly(mapper.valueToTree(doubleMap("prebid", emptyMap(), - "bidder", doubleMap("test-host", "unknownHost", "publisher_id", "ps4")))); - } - - @Test - public void shouldThrowErrorIfCannotBeParsedImpExtPrebid() { - // given - final String prebid = "prebid"; - final String bidderKey = "bidder"; - final String optionKey = "options"; - final String bidderName = "bidderName"; - final String optionValue = "1"; - final Map> bidderValue = - singletonMap(bidderName, doubleMap("test-host", "unknownHost", "publisher_id", "ps4")); - - final ObjectNode prebidJsonNodes = mapper.valueToTree( - singletonMap(prebid, doubleMap(optionKey, optionValue, bidderKey, bidderValue))); - - final Imp imp = Imp.builder().ext(prebidJsonNodes).build(); - final BidRequest bidRequest = givenBidRequest(singletonList(imp), identity()); - final AuctionContext auctionContext = givenRequestContext(bidRequest); - - given(privacyEnforcementService.mask(any(), anyMap(), any())) - .willReturn(Future.succeededFuture(singletonList(BidderPrivacyResult.builder() - .requestBidder(bidderName) - .build()))); - - // when - final Future result = target.holdAuction(auctionContext); - - // then - assertThat(result.failed()).isTrue(); - assertThat(result.cause()) - .hasMessageStartingWith("Error decoding imp.ext.prebid: " - + "Cannot construct instance of `org.prebid.server.proto.openrtb.ext.request.ExtOptions`"); + .containsExactly(mapper.valueToTree(Map.of( + "prebid", Map.of( + "storedrequest", Map.of("id", "id"), + "options", Map.of("echovideoattrs", true), + "is_rewarded_inventory", 1, + "adunitcode", "adCodeValue"), + "bidder", Map.of("test-host", "unknownHost", "publisher_id", "ps4")))); } @Test @@ -4162,13 +4143,6 @@ private static FledgeAuctionConfig givenFledgeAuctionConfig(String impId) { .build(); } - private static Map doubleMap(K key1, V value1, K key2, V value2) { - final Map map = new HashMap<>(); - map.put(key1, value1); - map.put(key2, value2); - return map; - } - private static ExtBidPrebid toExtBidPrebid(ObjectNode ext) { try { return mapper.treeToValue(ext.get("prebid"), ExtBidPrebid.class); diff --git a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java index d49f874c0e8..d6e6e6c3531 100644 --- a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java @@ -54,7 +54,6 @@ import org.prebid.server.bidder.rubicon.proto.request.RubiconBannerExt; import org.prebid.server.bidder.rubicon.proto.request.RubiconBannerExtRp; import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExt; -import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExtPrebid; import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExtRp; import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExtRpRtb; import org.prebid.server.bidder.rubicon.proto.request.RubiconImpExtRpTrack; @@ -90,7 +89,6 @@ import org.prebid.server.proto.openrtb.ext.request.ExtDealLine; import org.prebid.server.proto.openrtb.ext.request.ExtImpContext; import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; -import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebidFloors; import org.prebid.server.proto.openrtb.ext.request.ExtPublisher; import org.prebid.server.proto.openrtb.ext.request.ExtRegs; import org.prebid.server.proto.openrtb.ext.request.ExtRegsDsa; @@ -2993,152 +2991,6 @@ public void makeHttpRequestsShouldReturnOnlyLineItemRequestsWithExpectedFieldsWh givenImpExtRpTarget().put("line_item", "234")); } - @Test - public void makeHttpRequestsShouldFillImpExtWithFloorsForVideoImp() { - // given - final PriceFloorResult priceFloorResult = PriceFloorResult.of("video", BigDecimal.TEN, BigDecimal.TEN, "JPY"); - when(currencyConversionService.convertCurrency(any(), any(), any(), any())) - .thenReturn(BigDecimal.ONE); - when(priceFloorResolver.resolve(any(), any(), any(), any(), any(), any(), any())).thenReturn(priceFloorResult); - final JsonNode impFloorsNode = mapper.valueToTree(ExtImpPrebidFloors.of( - null, null, null, BigDecimal.TEN, "CUR")); - final ObjectNode givenImpExt = mapper.createObjectNode(); - final ObjectNode givenImpExtPrebid = mapper.createObjectNode(); - givenImpExtPrebid.set("floors", impFloorsNode); - givenImpExt.set("bidder", mapper.createObjectNode()); - givenImpExt.set("prebid", givenImpExtPrebid); - - final BidRequest bidRequest = givenBidRequest( - builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() - .floors(givenFloors(floors -> floors.data(givenFloorData( - floorData -> floorData.modelGroups(singletonList( - givenModelGroup(UnaryOperator.identity()))))))) - .build())), - builder -> builder.video(Video.builder().build()).ext(givenImpExt), - identity()); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - verify(priceFloorResolver).resolve(any(), any(), any(), eq(ImpMediaType.video), any(), any(), any()); - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1).doesNotContainNull() - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp).doesNotContainNull() - .extracting(Imp::getExt).doesNotContainNull() - .extracting(ext -> mapper.treeToValue(ext, RubiconImpExt.class)) - .extracting(RubiconImpExt::getPrebid) - .extracting(RubiconImpExtPrebid::getFloors) - .containsOnly(ExtImpPrebidFloors.of("video", BigDecimal.ONE, BigDecimal.ONE, BigDecimal.TEN, "CUR")); - } - - @Test - public void makeHttpRequestsShouldFillImpExtWithFloorsForBannerImp() { - // given - final PriceFloorResult priceFloorResult = PriceFloorResult.of("banner", BigDecimal.TEN, BigDecimal.TEN, "JPY"); - when(currencyConversionService.convertCurrency(any(), any(), any(), any())) - .thenReturn(BigDecimal.ONE); - when(priceFloorResolver.resolve(any(), any(), any(), any(), any(), any(), any())).thenReturn(priceFloorResult); - - final BidRequest bidRequest = givenBidRequest( - builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() - .floors(givenFloors(floors -> floors.data(givenFloorData( - floorData -> floorData.modelGroups(singletonList( - givenModelGroup(UnaryOperator.identity()))))))) - .build())), - builder -> builder.banner(Banner.builder().w(300).h(500).build()), - builder -> builder - .zoneId(4001) - .inventory(mapper.valueToTree(Inventory.of(singletonList("5-star"), singletonList("tech"))))); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - verify(priceFloorResolver).resolve(any(), any(), any(), eq(ImpMediaType.banner), any(), any(), any()); - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1).doesNotContainNull() - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp).doesNotContainNull() - .extracting(Imp::getExt).doesNotContainNull() - .extracting(ext -> mapper.treeToValue(ext, RubiconImpExt.class)) - .extracting(RubiconImpExt::getPrebid) - .extracting(RubiconImpExtPrebid::getFloors) - .containsOnly(ExtImpPrebidFloors.of("banner", BigDecimal.ONE, BigDecimal.ONE, null, null)); - } - - @Test - public void makeHttpRequestsShouldFillImpExtWithFloorsForNativeImp() { - // given - final PriceFloorResult priceFloorResult = PriceFloorResult.of("native", BigDecimal.TEN, BigDecimal.TEN, "JPY"); - when(currencyConversionService.convertCurrency(any(), any(), any(), any())) - .thenReturn(BigDecimal.ONE); - when(priceFloorResolver.resolve(any(), any(), any(), any(), any(), any(), any())).thenReturn(priceFloorResult); - - final BidRequest bidRequest = givenBidRequest( - builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() - .floors(givenFloors(floors -> floors.data(givenFloorData( - floorData -> floorData.modelGroups(singletonList( - givenModelGroup(UnaryOperator.identity()))))))) - .build())), - builder -> builder.xNative(Native.builder().ver("1.0").build()), - builder -> builder - .zoneId(4001) - .inventory(mapper.valueToTree(Inventory.of(singletonList("5-star"), singletonList("tech"))))); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - verify(priceFloorResolver).resolve(any(), any(), any(), eq(ImpMediaType.xNative), any(), any(), any()); - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1).doesNotContainNull() - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp).doesNotContainNull() - .extracting(Imp::getExt).doesNotContainNull() - .extracting(ext -> mapper.treeToValue(ext, RubiconImpExt.class)) - .extracting(RubiconImpExt::getPrebid) - .extracting(RubiconImpExtPrebid::getFloors) - .containsOnly(ExtImpPrebidFloors.of("native", BigDecimal.ONE, BigDecimal.ONE, null, null)); - } - - @Test - public void makeHttpRequestsShouldAssumeDefaultIpfCurrencyAsUSD() { - // given - final PriceFloorResult priceFloorResult = PriceFloorResult.of("video", BigDecimal.TEN, BigDecimal.TEN, null); - when(currencyConversionService.convertCurrency(any(), any(), any(), any())) - .thenReturn(BigDecimal.ONE); - when(priceFloorResolver.resolve(any(), any(), any(), any(), any(), any(), any())).thenReturn(priceFloorResult); - - final BidRequest bidRequest = givenBidRequest( - builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() - .debug(1) - .floors(givenFloors(floors -> floors.data(givenFloorData( - floorData -> floorData.modelGroups(singletonList( - givenModelGroup(UnaryOperator.identity()))))))) - .build())), - builder -> builder.id("123").video(Video.builder().build()), - builder -> builder - .zoneId(4001) - .inventory(mapper.valueToTree(Inventory.of(singletonList("5-star"), singletonList("tech"))))); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).containsExactly( - BidderError.badInput("Ipf for imp `123` provided floor with no currency, assuming USD")); - assertThat(result.getValue()).hasSize(1).doesNotContainNull() - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp).doesNotContainNull() - .extracting(Imp::getExt).doesNotContainNull() - .extracting(ext -> mapper.treeToValue(ext, RubiconImpExt.class)) - .extracting(RubiconImpExt::getPrebid) - .extracting(RubiconImpExtPrebid::getFloors) - .containsOnly(ExtImpPrebidFloors.of("video", BigDecimal.TEN, BigDecimal.TEN, null, null)); - } - @Test public void makeHttpRequestsShouldConvertBidFloor() { // given @@ -3176,49 +3028,6 @@ public void makeHttpRequestsShouldConvertBidFloor() { .containsExactly(BigDecimal.ONE); } - @Test - public void makeHttpRequestsShouldFillImpExtWithFloorsWhenBothVideoAndBanner() { - // given - final PriceFloorResult priceFloorResult = PriceFloorResult.of("video", BigDecimal.TEN, BigDecimal.TEN, "JPY"); - when(priceFloorResolver.resolve(any(), any(), any(), any(), any(), any(), any())).thenReturn(priceFloorResult); - when(currencyConversionService.convertCurrency(any(), any(), any(), any())) - .thenReturn(BigDecimal.ONE); - - final BidRequest bidRequest = givenBidRequest( - builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() - .floors(givenFloors(floors -> floors.data(givenFloorData( - floorData -> floorData.modelGroups(singletonList( - givenModelGroup(UnaryOperator.identity()))))))) - .build())), - builder -> builder - .video(Video.builder() - .mimes(singletonList("mime")) - .protocols(singletonList(1)) - .maxduration(10) - .linearity(10) - .build()) - .banner(Banner.builder() - .format(singletonList(Format.builder().h(300).w(250).build())) - .build()), - builder -> builder - .zoneId(4001) - .inventory(mapper.valueToTree(Inventory.of(singletonList("5-star"), singletonList("tech"))))); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1).doesNotContainNull() - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp).doesNotContainNull() - .extracting(Imp::getExt).doesNotContainNull() - .extracting(ext -> mapper.treeToValue(ext, RubiconImpExt.class)) - .extracting(RubiconImpExt::getPrebid) - .extracting(RubiconImpExtPrebid::getFloors) - .containsOnly(ExtImpPrebidFloors.of("video", BigDecimal.ONE, BigDecimal.ONE, null, null)); - } - @Test public void makeHttpRequestsShouldMoveSourceSchain() { // given