From 1d581e4372d92b08ed3851fab6cfc8112c46fdbb Mon Sep 17 00:00:00 2001 From: antonbabak Date: Fri, 28 Feb 2025 15:22:10 +0100 Subject: [PATCH 01/23] Multiple Bidder Codes --- .../server/auction/BidResponseCreator.java | 28 +- .../server/auction/ExchangeService.java | 47 ++ .../BidAdjustmentFactorResolver.java | 36 +- .../prebid/server/auction/model/BidInfo.java | 2 + .../BidAdjustmentsProcessor.java | 15 +- .../BidAdjustmentsResolver.java | 14 +- .../prebid/server/bidder/amx/AmxBidder.java | 7 +- .../prebid/server/bidder/model/BidderBid.java | 11 + .../bidder/pubmatic/PubmaticBidder.java | 1 + .../model/response/PubmaticBidExt.java | 2 + .../resetdigital/ResetDigitalBidder.java | 276 +++++--- .../resetdigital/request/ResetDigitalImp.java | 19 + .../request/ResetDigitalImpExt.java | 9 + .../request/ResetDigitalImpMediaType.java | 15 + .../request/ResetDigitalImpMediaTypes.java | 27 + .../request/ResetDigitalImpZone.java | 11 + .../request/ResetDigitalRequest.java | 15 + .../request/ResetDigitalSite.java | 13 + .../response/ResetDigitalBid.java | 31 + .../response/ResetDigitalResponse.java | 11 + .../server/bidder/vungle/VungleBidder.java | 9 +- .../org/prebid/server/metric/MetricName.java | 1 + .../org/prebid/server/metric/Metrics.java | 4 + .../resetdigital/ExtImpResetDigital.java | 9 + .../prebid/server/settings/model/Account.java | 3 + .../model/AccountAlternateBidderCodes.java | 15 + .../AccountAlternateBidderCodesBidder.java | 17 + .../bidder/ResetDigitalConfiguration.java | 7 +- .../org/prebid/server/util/BidderUtil.java | 31 + .../server/validation/RequestValidator.java | 17 +- .../validation/ResponseBidValidator.java | 73 ++- .../resources/bidder-config/resetdigital.yaml | 5 +- .../static/bidder-params/resetdigital.json | 22 +- .../auction/BidResponseCreatorTest.java | 242 +++---- .../server/auction/ExchangeServiceTest.java | 9 +- .../BidAdjustmentFactorResolverTest.java | 86 ++- .../BidAdjustmentsProcessorTest.java | 52 +- .../BidAdjustmentsResolverTest.java | 82 ++- .../server/bidder/amx/AmxBidderTest.java | 20 + .../bidder/pubmatic/PubmaticBidderTest.java | 29 +- .../resetdigital/ResetDigitalBidderTest.java | 617 +++++++++--------- .../bidder/vungle/VungleBidderTest.java | 8 +- .../SampleItProcessedBidderResponseHook.java | 1 + .../hooks/SampleItRawBidderResponseHook.java | 1 + .../org/prebid/server/metric/MetricsTest.java | 11 + .../validation/RequestValidatorTest.java | 65 -- .../validation/ResponseBidValidatorTest.java | 197 ++++++ .../server/it/amp/test-cache-request.json | 10 +- .../cache/update/test-auction-response.json | 6 + .../test-auction-33across-response.json | 5 +- .../aax/test-auction-aax-response.json | 5 +- .../aceex/test-auction-aceex-response.json | 5 +- .../test-auction-acuityads-response.json | 5 +- .../test-auction-adelement-response.json | 5 +- .../adf/test-auction-adf-response.json | 10 +- .../test-auction-adgeneration-response.json | 5 +- .../adhese/test-auction-adhese-response.json | 5 +- .../test-auction-adkernel-response.json | 5 +- .../test-auction-adkerneladn-response.json | 5 +- .../adman/test-auction-adman-response.json | 5 +- .../test-auction-admatic-response.json | 5 +- .../test-auction-admixer-response.json | 5 +- .../test-auction-adnuntius-response.json | 5 +- .../test-auction-adocean-response.json | 5 +- .../test-auction-adoppler-response.json | 5 +- .../adot/test-auction-adot-response.json | 5 +- .../adpone/test-auction-adpone-response.json | 5 +- .../test-auction-adprime-response.json | 5 +- .../test-auction-adquery-response.json | 5 +- .../adrino/test-auction-adrino-response.json | 5 +- .../test-auction-adsyield-response.json | 5 +- .../test-auction-adtarget-response.json | 5 +- .../test-auction-adtelligent-response.json | 5 +- .../test-auction-adtonos-response.json | 5 +- .../test-auction-adtrgtme-response.json | 5 +- .../test-auction-advangelists-response.json | 5 +- .../adview/test-auction-adview-response.json | 5 +- .../adxcg/test-auction-adxcg-response.json | 5 +- .../test-auction-adyoulike-response.json | 5 +- .../aidem/test-auction-aidem-response.json | 5 +- .../aja/test-auction-aja-response.json | 5 +- .../test-auction-algorix-response.json | 5 +- .../alkimi/test-auction-alkimi-response.json | 5 +- .../amx/test-auction-amx-response.json | 5 +- .../test-auction-apacdex-response.json | 5 +- .../appush/test-auction-appush-response.json | 5 +- .../aso/test-auction-aso-response.json | 5 +- ...test-auction-audiencenetwork-response.json | 5 +- .../test-auction-automatad-response.json | 5 +- .../avocet/test-auction-avocet-response.json | 5 +- .../axis/test-auction-axis-response.json | 5 +- .../axonix/test-auction-axonix-response.json | 5 +- .../bcmint/test-auction-bcmint-response.json | 5 +- .../test-auction-beachfront-response.json | 5 +- .../test-auction-beintoo-response.json | 5 +- .../test-auction-bematterfull-response.json | 5 +- .../test-auction-between-response.json | 5 +- .../test-auction-beyondmedia-response.json | 5 +- .../test-auction-bidagency-response.json | 5 +- .../test-auction-bidmachine-response.json | 5 +- .../test-auction-bidmatic-response.json | 5 +- .../test-auction-bidmyadz-response.json | 5 +- .../test-auction-bidscube-response.json | 5 +- .../test-auction-bidstack-response.json | 5 +- .../bigoad/test-auction-bigoad-response.json | 5 +- .../blasto/test-auction-blasto-response.json | 5 +- .../bliink/test-auction-bliink-response.json | 5 +- .../blue/test-auction-blue-response.json | 5 +- .../test-auction-bluesea-response.json | 5 +- .../bmtm/test-auction-bmtm-response.json | 5 +- .../test-auction-boldwin-response.json | 5 +- .../brave/test-auction-brave-response.json | 5 +- .../bwx/test-auction-bwx-response.json | 5 +- ...est-auction-cadentaperturemx-response.json | 5 +- .../ccx/test-auction-ccx-response.json | 5 +- .../test-auction-cointraffic-response.json | 5 +- .../test-auction-coinzilla-response.json | 5 +- .../test-auction-colossusssp-response.json | 5 +- .../test-auction-colossus-response.json | 5 +- .../test-auction-compass-response.json | 5 +- .../test-auction-concert-response.json | 5 +- .../test-auction-connectad-response.json | 5 +- .../test-auction-connektai-response.json | 5 +- .../test-auction-consumable-response.json | 5 +- .../test-auction-copper6-response.json | 5 +- .../test-auction-copper6ssp-response.json | 5 +- .../test-auction-cpmstar-response.json | 5 +- .../criteo/test-auction-criteo-response.json | 5 +- .../cwire/test-auction-cwire-response.json | 5 +- .../test-auction-datablocks-response.json | 5 +- .../test-auction-decenterads-response.json | 5 +- .../test-auction-deepintent-response.json | 5 +- .../test-auction-definemedia-response.json | 5 +- .../test-auction-dianomi-response.json | 5 +- .../dianomi/test-dianomi-bid-response.json | 5 +- .../test-auction-displayio-response.json | 5 +- .../dmx/test-auction-dmx-response.json | 5 +- .../test-auction-driftpixel-response.json | 5 +- .../test-auction-dxkulture-response.json | 5 +- .../test-auction-edge226-response.json | 5 +- .../test-auction-embimedia-response.json | 5 +- .../emtv/test-auction-emtv-response.json | 5 +- .../test-auction-emxdigital-response.json | 5 +- .../test-auction-eplanning-response.json | 5 +- .../epom/test-auction-epom-response.json | 5 +- .../alias/test-auction-epsilon-response.json | 5 +- .../test-auction-epsilon-response.json | 5 +- .../test-auction-escalax-response.json | 5 +- .../test-auction-evolution-response.json | 5 +- .../test-auction-felixads-response.json | 5 +- .../test-auction-filmzie-response.json | 5 +- .../test-auction-finative-response.json | 5 +- .../flipp/test-auction-flipp-response.json | 5 +- ...loors-test-auction-response-no-signal.json | 5 +- .../floors/floors-test-auction-response.json | 5 +- .../test-auction-freewheelssp-response.json | 5 +- .../test-auction-frvradn-response.json | 5 +- .../gamma/test-auction-gamma-response.json | 5 +- .../test-auction-gamoshi-response.json | 5 +- .../test-auction-generic-response.json | 2 +- .../test-auction-generic-response.json | 3 +- .../test-cache-generic-request.json | 3 +- .../test-auction-globalsun-response.json | 5 +- .../test-auction-gothamads-response.json | 5 +- .../test-auction-greedygame-response.json | 5 +- .../grid/test-auction-grid-response.json | 3 +- .../gumgum/test-auction-gumgum-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-huaweiads-auction-response.json | 5 +- .../test-auction-iionads-response.json | 5 +- .../imds/test-auction-imds-response.json | 5 +- .../test-auction-impactify-response.json | 5 +- .../test-auction-improvedigital-response.json | 5 +- .../test-auction-indicue-response.json | 5 +- .../infytv/test-auction-infytv-response.json | 5 +- .../inmobi/test-auction-inmobi-response.json | 5 +- .../test-auction-insticator-response.json | 5 +- ...st-auction-interactiveoffers-response.json | 5 +- .../test-auction-intertech-response.json | 5 +- .../test-auction-invibes-response.json | 5 +- .../iqx/test-auction-iqx-response.json | 5 +- .../iqzone/test-auction-iqzone-response.json | 5 +- .../openrtb2/ix/test-auction-ix-response.json | 5 +- .../test-auction-jdpmedia-response.json | 5 +- .../jixie/test-auction-jixie-response.json | 5 +- .../kargo/test-auction-kargo-response.json | 5 +- .../kayzen/test-auction-kayzen-response.json | 5 +- .../kidoz/test-auction-kidoz-response.json | 5 +- .../test-auction-kiviads-response.json | 5 +- .../test-auction-krushmedia-response.json | 5 +- .../test-auction-lemmaDigital-response.json | 5 +- .../test-auction-liftoff-response.json | 5 +- ...est-auction-limelightDigital-response.json | 5 +- .../test-auction-lmkiviads-response.json | 5 +- .../test-auction-lockerdome-response.json | 5 +- .../logan/test-auction-logan-response.json | 5 +- .../test-auction-logicad-response.json | 5 +- .../loopme/test-auction-loopme-response.json | 5 +- .../loyal/test-auction-loyal-response.json | 5 +- .../test-auction-lunamedia-response.json | 5 +- .../test-auction-mabidder-response.json | 5 +- .../test-auction-madvertise-response.json | 5 +- .../test-auction-magnite-response.json | 3 +- .../test-auction-markapp-response.json | 5 +- .../test-auction-marsmedia-response.json | 5 +- .../test-auction-mediago-response.json | 5 +- .../test-auction-medianet-response.json | 5 +- .../test-auction-melozen-response.json | 5 +- .../metax/test-auction-metax-response.json | 5 +- .../mgid/test-auction-mgid-response.json | 5 +- .../mgidx/test-auction-mgidx-response.json | 5 +- .../test-auction-minutemedia-response.json | 5 +- .../test-auction-missena-response.json | 5 +- .../test-auction-mobfoxpb-response.json | 5 +- .../test-auction-mobilefuse-response.json | 5 +- .../test-auction-motorik-response.json | 5 +- ...auction-generic-genericAlias-response.json | 12 + ...st-cache-generic-genericAlias-request.json | 12 + .../test-auction-nextmillennium-response.json | 5 +- .../nobid/test-auction-nobid-response.json | 5 +- .../oms/test-auction-oms-response.json | 5 +- .../onetag/test-auction-onetag-response.json | 5 +- .../test-auction-openweb-response.json | 5 +- .../openx/test-auction-openx-response.json | 5 +- .../test-auction-operaads-response.json | 5 +- .../oraki/test-auction-oraki-response.json | 5 +- .../test-auction-orbidder-response.json | 5 +- .../test-auction-outbrain-response.json | 5 +- .../ownadx/test-auction-ownadx-response.json | 5 +- .../pangle/test-auction-pangle-response.json | 5 +- .../pgam/test-auction-pgam-response.json | 5 +- .../test-auction-pgamssp-response.json | 5 +- .../test-auction-playdigo-response.json | 5 +- .../test-auction-preciso-response.json | 5 +- .../test-auction-pubmatic-response.json | 5 +- .../test-auction-pubnative-response.json | 5 +- .../test-auction-pubrise-response.json | 5 +- .../test-auction-pulsepoint-response.json | 5 +- .../pwbid/test-auction-pwbid-response.json | 5 +- .../openrtb2/qt/test-auction-qt-response.json | 5 +- .../test-auction-readpeak-response.json | 4 +- ...test-auction-relevantdigital-response.json | 5 +- .../test-auction-resetdigital-request.json | 23 +- .../test-auction-resetdigital-response.json | 24 +- .../test-resetdigital-bid-request.json | 64 +- .../test-resetdigital-bid-response.json | 29 +- .../test-auction-revcontent-response.json | 5 +- .../test-auction-richaudience-response.json | 5 +- .../rise/test-auction-rise-response.json | 5 +- .../roulax/test-auction-roulax-response.json | 5 +- .../test-auction-rtbhouse-response.json | 5 +- .../test-auction-rubicon-response.json | 3 +- .../test-auction-salunamedia-response.json | 5 +- .../test-auction-screencore-response.json | 5 +- ...test-auction-seedingAlliance-response.json | 5 +- .../test-auction-sharethrough-response.json | 5 +- .../test-auction-silvermob-response.json | 5 +- .../test-auction-silverpush-response.json | 5 +- .../smaato/test-auction-smaato-response.json | 5 +- .../test-auction-smartadserver-response.json | 5 +- .../test-auction-smarthub-response.json | 5 +- .../test-auction-smartrtb-response.json | 5 +- .../smartx/test-auction-smartx-response.json | 5 +- .../test-auction-smartyads-response.json | 5 +- .../test-auction-smilewanted-response.json | 5 +- .../test-auction-smrtconnect-response.json | 5 +- .../sonobi/test-auction-sonobi-response.json | 5 +- .../sovrn/test-auction-sovrn-response.json | 5 +- .../test-auction-sovrnxsp-response.json | 5 +- .../sspbc/test-auction-sspbc-response.json | 5 +- .../storedresponse/test-auction-response.json | 3 + .../storedresponse/test-cache-request.json | 5 +- .../test-auction-streamlyn-response.json | 5 +- .../test-auction-stroeercore-response.json | 10 +- .../test-auction-suntContent-response.json | 5 +- .../test-auction-taboola-response.json | 10 +- .../tappx/test-auction-tappx-response.json | 5 +- .../teads/test-auction-teads-response.json | 3 +- .../test-auction-telaria-response.json | 5 +- .../tgm/test-auction-tgm-response.json | 5 +- .../theadx/test-auction-theadx-response.json | 5 +- .../test-auction-thetradedesk-response.json | 5 +- ...st-auction-thirtythreeacross-response.json | 5 +- .../tpmn/test-auction-tpmn-response.json | 5 +- .../test-auction-tradplus-response.json | 5 +- .../test-auction-trafficgate-response.json | 5 +- .../tredio/test-auction-tredio-response.json | 5 +- .../test-auction-triplelift-response.json | 5 +- ...st-auction-triplelift-native-response.json | 5 +- .../test-auction-trustedstack-response.json | 5 +- .../ttx/test-auction-ttx-response.json | 5 +- .../test-auction-ucfunnel-response.json | 5 +- .../test-auction-undertone-response.json | 5 +- .../test-auction-unicorn-response.json | 5 +- .../unruly/test-auction-unruly-response.json | 5 +- .../test-auction-vidazoo-response.json | 5 +- .../test-auction-videobyte-response.json | 5 +- .../test-auction-videoheroes-response.json | 5 +- .../test-auction-vidoomy-response.json | 5 +- .../vimayx/test-auction-vimayx-response.json | 5 +- ...test-auction-visiblemeasures-response.json | 5 +- .../visx/test-auction-visx-response.json | 5 +- .../vox/test-auction-vox-response.json | 5 +- .../vrtcal/test-auction-vrtcal-response.json | 5 +- .../vungle/test-auction-vungle-response.json | 5 +- .../test-auction-xeworks-response.json | 5 +- .../xtrmqb/test-auction-xtrmqb-response.json | 5 +- .../test-auction-yahooads-response.json | 5 +- .../yandex/test-auction-yandex-response.json | 5 +- .../test-auction-yeahmobi-response.json | 5 +- .../test-auction-yearxero-response.json | 5 +- .../test-auction-yieldlab-response.json | 5 +- .../test-auction-yieldmo-response.json | 5 +- .../test-auction-yieldone-response.json | 5 +- .../test-auction-zeroclickfraud-response.json | 5 +- ...test-auction-zeta_global_ssp-response.json | 5 +- .../test-auction-zmaticoo-response.json | 5 +- 339 files changed, 2728 insertions(+), 1092 deletions(-) create mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImp.java create mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpExt.java create mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaType.java create mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaTypes.java create mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpZone.java create mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalRequest.java create mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalSite.java create mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalBid.java create mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalResponse.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/resetdigital/ExtImpResetDigital.java create mode 100644 src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java create mode 100644 src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 4242281a5dd..642ff12c5fd 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -431,9 +431,15 @@ private List toBidderResponseInfos(CategoryMappingResult cat final BidderSeatBid seatBid = bidderResponse.getSeatBid(); for (final BidderBid bidderBid : seatBid.getBids()) { - final Bid bid = bidderBid.getBid(); - final BidType type = bidderBid.getType(); - final BidInfo bidInfo = toBidInfo(bid, type, imps, bidder, categoryMappingResult, cacheInfo, account); + final BidInfo bidInfo = toBidInfo( + bidderBid.getBid(), + bidderBid.getType(), + bidderBid.getSeat(), + imps, + bidder, + categoryMappingResult, + cacheInfo, + account); bidInfos.add(bidInfo); } @@ -453,6 +459,7 @@ private List toBidderResponseInfos(CategoryMappingResult cat private BidInfo toBidInfo(Bid bid, BidType type, + String seat, List imps, String bidder, CategoryMappingResult categoryMappingResult, @@ -464,6 +471,7 @@ private BidInfo toBidInfo(Bid bid, .bid(bid) .bidType(type) .bidder(bidder) + .seat(seat) .correspondingImp(correspondingImp) .ttl(resolveTtl(bid, type, correspondingImp, cacheInfo, account)) .vastTtl(type == BidType.video ? resolveVastTtl(bid, correspondingImp, cacheInfo, account) : null) @@ -1429,12 +1437,6 @@ private SeatBid toSeatBid(List bidInfos, Map> bidErrors, Map> bidWarnings) { - final String bidder = bidInfos.stream() - .map(BidInfo::getBidder) - .findFirst() - // Should never occur - .orElseThrow(() -> new IllegalArgumentException("Bidder was not defined for bidInfo")); - final List bids = bidInfos.stream() .map(bidInfo -> injectAdmWithCacheInfo( bidInfo, @@ -1451,8 +1453,14 @@ private SeatBid toSeatBid(List bidInfos, .filter(Objects::nonNull) .toList(); + final String seat = bidInfos.stream() + .map(BidInfo::getSeat) + .findFirst() + // Should never occur + .orElseThrow(() -> new IllegalArgumentException("BidderCode was not defined for bidInfo")); + return SeatBid.builder() - .seat(bidder) + .seat(seat) .bid(bids) .group(0) // prebid cannot support roadblocking .build(); diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index 56cd8192501..4c26bf381f7 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -1,5 +1,6 @@ package org.prebid.server.auction; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.App; @@ -73,6 +74,7 @@ import org.prebid.server.metric.Metrics; import org.prebid.server.model.CaseInsensitiveMultiMap; import org.prebid.server.model.UpdateResult; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; import org.prebid.server.proto.openrtb.ext.ExtPrebidBidders; import org.prebid.server.proto.openrtb.ext.request.ExtApp; import org.prebid.server.proto.openrtb.ext.request.ExtBidderConfigOrtb; @@ -88,6 +90,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequestTargeting; import org.prebid.server.proto.openrtb.ext.request.ExtSite; import org.prebid.server.proto.openrtb.ext.request.ExtUser; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import org.prebid.server.settings.model.Account; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ListUtil; @@ -124,6 +128,9 @@ public class ExchangeService { 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 static final TypeReference> EXT_PREBID_TYPE_REFERENCE = + new TypeReference<>() { + }; private final double logSamplingRate; private final BidderCatalog bidderCatalog; @@ -1225,9 +1232,49 @@ private Future requestBids(BidderRequest bidderRequest, requestHeaders, aliases, debugResolver.resolveDebugForBidder(auctionContext, resolvedBidderName))) + .map(seatBid -> populateBidderCode(seatBid, bidderName)) .map(seatBid -> BidderResponse.of(bidderName, seatBid, responseTime(bidderRequestStartTime))); } + private BidderSeatBid populateBidderCode(BidderSeatBid seatBid, String bidderName) { + return seatBid.with(seatBid.getBids().stream() + .map(bidderBid -> bidderBid.toBuilder() + .seat(bidderBid.getSeat() == null ? bidderName : bidderBid.getSeat()) + .bid(bidderBid.getBid().toBuilder().ext(prepareBidExt(bidderBid.getBid(), bidderName)).build()) + .build()) + .toList()); + } + + private ObjectNode prepareBidExt(Bid bid, String bidderName) { + final ObjectNode bidExt = bid.getExt(); + final ExtPrebid extPrebid = getExtPrebid(bidExt); + final ExtBidPrebid extBidPrebid = extPrebid != null ? extPrebid.getPrebid() : null; + final ExtBidPrebidMeta meta = extBidPrebid != null ? extBidPrebid.getMeta() : null; + + final ExtBidPrebidMeta updatedMeta = Optional.ofNullable(meta) + .map(ExtBidPrebidMeta::toBuilder) + .orElseGet(ExtBidPrebidMeta::builder) + .adapterCode(bidderName) + .build(); + + final ExtBidPrebid modifiedExtBidPrebid = extBidPrebid != null + ? extBidPrebid.toBuilder().meta(updatedMeta).build() + : ExtBidPrebid.builder().meta(updatedMeta).build(); + + final ObjectNode updatedBidExt = bidExt != null ? bidExt : mapper.mapper().createObjectNode(); + updatedBidExt.set(PREBID_EXT, mapper.mapper().valueToTree(modifiedExtBidPrebid)); + + return updatedBidExt; + } + + private ExtPrebid getExtPrebid(ObjectNode bidExt) { + try { + return bidExt != null ? mapper.mapper().convertValue(bidExt, EXT_PREBID_TYPE_REFERENCE) : null; + } catch (IllegalArgumentException e) { + return null; + } + } + private BidRequest adjustTmax(BidRequest bidRequest, long startTime, int adjustmentFactor, diff --git a/src/main/java/org/prebid/server/auction/adjustment/BidAdjustmentFactorResolver.java b/src/main/java/org/prebid/server/auction/adjustment/BidAdjustmentFactorResolver.java index fa0013d683f..3f41b29110f 100644 --- a/src/main/java/org/prebid/server/auction/adjustment/BidAdjustmentFactorResolver.java +++ b/src/main/java/org/prebid/server/auction/adjustment/BidAdjustmentFactorResolver.java @@ -14,25 +14,41 @@ public class BidAdjustmentFactorResolver { public BigDecimal resolve(ImpMediaType impMediaType, ExtRequestBidAdjustmentFactors adjustmentFactors, - String bidder) { + String bidder, + String seat) { final EnumMap> adjustmentFactorsByMediaTypes = adjustmentFactors.getMediatypes(); + final Map adjustmentsFactors = adjustmentFactors.getAdjustments(); - final BigDecimal effectiveBidderAdjustmentFactor = Optional.ofNullable(adjustmentFactors.getAdjustments()) - .map(factors -> factors.get(bidder)) + return resolveFromMediaTypes(impMediaType, seat, adjustmentFactorsByMediaTypes) + .or(() -> resolveFromAdjustments(seat, adjustmentsFactors)) + .or(() -> resolveFromMediaTypes(impMediaType, bidder, adjustmentFactorsByMediaTypes)) + .or(() -> resolveFromAdjustments(bidder, adjustmentsFactors)) .orElse(BigDecimal.ONE); + } + + private static Optional resolveFromMediaTypes( + ImpMediaType mediaType, + String bidderCode, + EnumMap> adjustmentFactors) { - if (MapUtils.isEmpty(adjustmentFactorsByMediaTypes)) { - return effectiveBidderAdjustmentFactor; + if (MapUtils.isEmpty(adjustmentFactors)) { + return Optional.empty(); } - return Optional.ofNullable(impMediaType) - .map(adjustmentFactorsByMediaTypes::get) + return Optional.ofNullable(mediaType) + .map(adjustmentFactors::get) .flatMap(factors -> factors.entrySet().stream() - .filter(entry -> StringUtils.equalsIgnoreCase(entry.getKey(), bidder)) + .filter(entry -> StringUtils.equalsIgnoreCase(entry.getKey(), bidderCode)) .map(Map.Entry::getValue) - .findFirst()) - .orElse(effectiveBidderAdjustmentFactor); + .findFirst()); + } + + private static Optional resolveFromAdjustments(String bidderCode, + Map adjustmentFactors) { + + return Optional.ofNullable(adjustmentFactors) + .map(factors -> factors.get(bidderCode)); } } diff --git a/src/main/java/org/prebid/server/auction/model/BidInfo.java b/src/main/java/org/prebid/server/auction/model/BidInfo.java index aa3be49fd48..f2e3fc7b438 100644 --- a/src/main/java/org/prebid/server/auction/model/BidInfo.java +++ b/src/main/java/org/prebid/server/auction/model/BidInfo.java @@ -21,6 +21,8 @@ public class BidInfo { String bidder; + String seat; + BidType bidType; CacheInfo cacheInfo; diff --git a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java index 1136876c7f6..b8cc890e44d 100644 --- a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java +++ b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java @@ -98,12 +98,14 @@ private BidderBid applyBidAdjustments(BidderBid bidderBid, final Price priceWithFactorsApplied = applyBidAdjustmentFactors( originalPrice, bidder, + bidderBid.getSeat(), bidRequest, mediaType); final Price priceWithAdjustmentsApplied = applyBidAdjustmentRules( priceWithFactorsApplied, bidder, + bidderBid.getSeat(), bidRequest, bidAdjustments, mediaType, @@ -154,26 +156,31 @@ private Price getOriginalPrice(BidderBid bidderBid) { private Price applyBidAdjustmentFactors(Price bidPrice, String bidder, + String seat, BidRequest bidRequest, ImpMediaType mediaType) { final String bidCurrency = bidPrice.getCurrency(); final BigDecimal price = bidPrice.getValue(); - final BigDecimal priceAdjustmentFactor = bidAdjustmentForBidder(bidder, bidRequest, mediaType); + final BigDecimal priceAdjustmentFactor = bidAdjustmentForBidder(bidder, seat, bidRequest, mediaType); final BigDecimal adjustedPrice = adjustPrice(priceAdjustmentFactor, price); return Price.of(bidCurrency, adjustedPrice.compareTo(price) != 0 ? adjustedPrice : price); } - private BigDecimal bidAdjustmentForBidder(String bidder, BidRequest bidRequest, ImpMediaType mediaType) { + private BigDecimal bidAdjustmentForBidder(String bidder, + String seat, + BidRequest bidRequest, + ImpMediaType mediaType) { + final ExtRequestBidAdjustmentFactors adjustmentFactors = extBidAdjustmentFactors(bidRequest); if (adjustmentFactors == null) { return null; } final ImpMediaType targetMediaType = mediaType == ImpMediaType.video_instream ? ImpMediaType.video : mediaType; - return bidAdjustmentFactorResolver.resolve(targetMediaType, adjustmentFactors, bidder); + return bidAdjustmentFactorResolver.resolve(targetMediaType, adjustmentFactors, bidder, seat); } private static ExtRequestBidAdjustmentFactors extBidAdjustmentFactors(BidRequest bidRequest) { @@ -189,6 +196,7 @@ private static BigDecimal adjustPrice(BigDecimal priceAdjustmentFactor, BigDecim private Price applyBidAdjustmentRules(Price bidPrice, String bidder, + String seat, BidRequest bidRequest, BidAdjustments bidAdjustments, ImpMediaType mediaType, @@ -200,6 +208,7 @@ private Price applyBidAdjustmentRules(Price bidPrice, bidAdjustments, mediaType, bidder, + seat, dealId); } } diff --git a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java index ffac1cbc51a..76766aced79 100644 --- a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java +++ b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java @@ -1,6 +1,7 @@ package org.prebid.server.bidadjustments; import com.iab.openrtb.request.BidRequest; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidadjustments.model.BidAdjustmentType; import org.prebid.server.bidadjustments.model.BidAdjustments; @@ -42,14 +43,23 @@ public Price resolve(Price initialPrice, BidAdjustments bidAdjustments, ImpMediaType targetMediaType, String targetBidder, + String targetSeat, String targetDealId) { - final List adjustmentsRules = findRules( + List adjustmentsRules = findRules( bidAdjustments, targetMediaType, - targetBidder, + targetSeat, targetDealId); + if (CollectionUtils.isEmpty(adjustmentsRules)) { + adjustmentsRules = findRules( + bidAdjustments, + targetMediaType, + targetBidder, + targetDealId); + } + return adjustPrice(initialPrice, adjustmentsRules, bidRequest); } diff --git a/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java b/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java index bed5622ec06..2d587b37ab6 100644 --- a/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java +++ b/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java @@ -173,8 +173,11 @@ private BidderBid createBidderBid(Bid bid, String cur, List errors) errors.add(BidderError.badInput(e.getMessage())); return null; } - // TODO: After adding support to change seat data, add bid.ext bidderCode processing - return BidderBid.of(resolveBid(bid, amxBidExt.getDemandSource()), getBidType(amxBidExt), cur); + return BidderBid.of( + resolveBid(bid, amxBidExt.getDemandSource()), + getBidType(amxBidExt), + amxBidExt.getBidderCode(), + cur); } private AmxBidExt parseBidderExt(ObjectNode ext) { diff --git a/src/main/java/org/prebid/server/bidder/model/BidderBid.java b/src/main/java/org/prebid/server/bidder/model/BidderBid.java index ef4b18eaa2d..559d072cdd4 100644 --- a/src/main/java/org/prebid/server/bidder/model/BidderBid.java +++ b/src/main/java/org/prebid/server/bidder/model/BidderBid.java @@ -19,6 +19,8 @@ public class BidderBid { */ Bid bid; + String seat; + /** * Will become response.seatbid[i].bid.ext.prebid.type in the final OpenRTB response. */ @@ -52,4 +54,13 @@ public static BidderBid of(Bid bid, BidType bidType, String bidCurrency) { .bidCurrency(bidCurrency) .build(); } + + public static BidderBid of(Bid bid, BidType bidType, String seat, String bidCurrency) { + return BidderBid.builder() + .bid(bid) + .type(bidType) + .bidCurrency(bidCurrency) + .seat(seat) + .build(); + } } diff --git a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java index 4a9e9818688..3072091d198 100644 --- a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java +++ b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java @@ -554,6 +554,7 @@ private BidderBid resolveBidderBid(Bid bid, String currency, List b .type(bidType) .bidCurrency(currency) .dealPriority(getDealPriority(pubmaticBidExt)) + .seat(pubmaticBidExt == null ? null : pubmaticBidExt.getMarketplace()) .build(); } diff --git a/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticBidExt.java b/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticBidExt.java index b469bbd59b6..f41bac7da89 100644 --- a/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticBidExt.java +++ b/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticBidExt.java @@ -17,4 +17,6 @@ public class PubmaticBidExt { @JsonProperty("prebiddealpriority") Integer prebidDealPriority; + + String marketplace; } diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java b/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java index 3bc78b588b0..09184177566 100644 --- a/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java +++ b/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java @@ -1,182 +1,242 @@ package org.prebid.server.bidder.resetdigital; +import com.fasterxml.jackson.core.type.TypeReference; +import com.iab.openrtb.request.Audio; +import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Site; +import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; -import com.iab.openrtb.response.BidResponse; -import com.iab.openrtb.response.SeatBid; +import io.vertx.core.MultiMap; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.ObjectUtils; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; import org.prebid.server.bidder.model.BidderError; import org.prebid.server.bidder.model.HttpRequest; -import org.prebid.server.bidder.model.Price; import org.prebid.server.bidder.model.Result; -import org.prebid.server.currency.CurrencyConversionService; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalImp; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpMediaType; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpMediaTypes; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpZone; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalRequest; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalSite; +import org.prebid.server.bidder.resetdigital.response.ResetDigitalBid; +import org.prebid.server.bidder.resetdigital.response.ResetDigitalResponse; import org.prebid.server.exception.PreBidException; import org.prebid.server.json.DecodeException; import org.prebid.server.json.JacksonMapper; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.resetdigital.ExtImpResetDigital; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; -import java.math.BigDecimal; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.stream.Stream; +import java.util.Set; -public class ResetDigitalBidder implements Bidder { +public class ResetDigitalBidder implements Bidder { - private static final String DEFAULT_CURRENCY = "USD"; + private static final TypeReference> IMP_EXT_TYPE_REFERENCE = + new TypeReference<>() { + }; + private static final String BID_CURRENCY = "USD"; private final String endpointUrl; - private final CurrencyConversionService currencyConversionService; private final JacksonMapper mapper; - public ResetDigitalBidder(String endpointUrl, - CurrencyConversionService currencyConversionService, - JacksonMapper mapper) { - + public ResetDigitalBidder(String endpointUrl, JacksonMapper mapper) { this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); - this.currencyConversionService = Objects.requireNonNull(currencyConversionService); this.mapper = Objects.requireNonNull(mapper); } @Override - public Result>> makeHttpRequests(BidRequest request) { - final List bannerImps = new ArrayList<>(); - final List videoImps = new ArrayList<>(); - final List audioImps = new ArrayList<>(); - Price bidFloorPrice; + public Result>> makeHttpRequests(BidRequest request) { + final List> requests = new ArrayList<>(); + final List errors = new ArrayList<>(); - for (Imp imp : request.getImp()) { + for (Imp imp: request.getImp()) { try { - bidFloorPrice = resolveBidFloor(imp, request); + final ExtImpResetDigital extImp = parseImpExt(imp); + final ResetDigitalImp resetDigitalImp = makeImp(request, imp, extImp); + final HttpRequest httpRequest = BidderUtil.defaultRequest( + makeRequest(request, resetDigitalImp), + makeHeaders(request), + endpointUrl, + Set.of(resetDigitalImp.getImpId()), + mapper); + requests.add(httpRequest); } catch (PreBidException e) { - return Result.withError(BidderError.badInput(e.getMessage())); + errors.add(BidderError.badInput(e.getMessage())); } - populateBannerImps(bannerImps, bidFloorPrice, imp); - populateVideoImps(videoImps, bidFloorPrice, imp); - populateAudiImps(audioImps, bidFloorPrice, imp); } - return Result.withValues(getHttpRequests(request, bannerImps, videoImps, audioImps)); + return Result.of(requests, errors); } - private List> getHttpRequests(BidRequest request, - List bannerImps, - List videoImps, - List audioImps) { + private ExtImpResetDigital parseImpExt(Imp imp) throws PreBidException { + try { + return mapper.mapper().convertValue(imp.getExt(), IMP_EXT_TYPE_REFERENCE).getBidder(); + } catch (IllegalArgumentException e) { + throw new PreBidException(e.getMessage()); + } + } - return Stream.of(bannerImps, videoImps, audioImps) - .filter(CollectionUtils::isNotEmpty) - .map(imp -> makeHttpRequest(request, imp)) - .toList(); + private static ResetDigitalImp makeImp(BidRequest request, Imp imp, ExtImpResetDigital extImp) { + return ResetDigitalImp.builder() + .bidId(request.getId()) + .impId(imp.getId()) + .mediaTypes(resolveMediaTypes(imp)) + .zoneId(extImp.getPlacementId() == null ? null : ResetDigitalImpZone.of(extImp.getPlacementId())) + .build(); } - private HttpRequest makeHttpRequest(BidRequest bidRequest, List imp) { - final BidRequest outgoingRequest = bidRequest.toBuilder().imp(imp).build(); + private static ResetDigitalImpMediaTypes resolveMediaTypes(Imp imp) { + final Banner banner = imp.getBanner(); + final Video video = imp.getVideo(); + final Audio audio = imp.getAudio(); + + if (banner != null) { + final ResetDigitalImpMediaType mediaType = makeBanner(banner); + return mediaType == null ? null : ResetDigitalImpMediaTypes.banner(mediaType); + } else if (video != null) { + final ResetDigitalImpMediaType mediaType = makeVideo(video); + return mediaType == null ? null : ResetDigitalImpMediaTypes.video(mediaType); + } else if (audio != null) { + final ResetDigitalImpMediaType mediaType = makeAudio(audio); + return mediaType == null ? null : ResetDigitalImpMediaTypes.audio(mediaType); + } else { + throw new PreBidException("Banner, video or audio must be present in the imp %s".formatted(imp.getId())); + } + } - return BidderUtil.defaultRequest(outgoingRequest, endpointUrl, mapper); + private static ResetDigitalImpMediaType makeBanner(Banner banner) { + return makeMediaType(banner.getW(), banner.getH(), null); } - private static Imp modifyImp(Imp imp, Price bidFloorPrice) { - return imp.toBuilder() - .bidfloorcur(bidFloorPrice.getCurrency()) - .bidfloor(bidFloorPrice.getValue()) - .build(); + private static ResetDigitalImpMediaType makeVideo(Video video) { + return makeMediaType(video.getW(), video.getH(), video.getMimes()); } - private Price resolveBidFloor(Imp imp, BidRequest bidRequest) { - final Price initialBidFloorPrice = Price.of(imp.getBidfloorcur(), imp.getBidfloor()); - return BidderUtil.isValidPrice(initialBidFloorPrice) - ? convertBidFloor(initialBidFloorPrice, imp.getId(), bidRequest) - : initialBidFloorPrice; + private static ResetDigitalImpMediaType makeAudio(Audio audio) { + return makeMediaType(null, null, audio.getMimes()); } - private Price convertBidFloor(Price bidFloorPrice, String impId, BidRequest bidRequest) { - final String bidFloorCur = bidFloorPrice.getCurrency(); - try { - final BigDecimal convertedPrice = currencyConversionService - .convertCurrency(bidFloorPrice.getValue(), bidRequest, bidFloorCur, DEFAULT_CURRENCY); - - return Price.of(DEFAULT_CURRENCY, convertedPrice); - } catch (PreBidException e) { - throw new PreBidException( - "Unable to convert provided bid floor currency from %s to %s for imp `%s`" - .formatted(bidFloorCur, DEFAULT_CURRENCY, impId)); + private static ResetDigitalImpMediaType makeMediaType(Integer width, Integer height, List mimes) { + final boolean hasValidSizes = isValidSizeValue(width) && isValidSizeValue(height); + final boolean hasMimes = CollectionUtils.isNotEmpty(mimes); + + if (!hasValidSizes && !hasMimes) { + return null; } + + return ResetDigitalImpMediaType.builder() + .sizes(hasValidSizes ? List.of(List.of(width, height)) : null) + .mimes(hasMimes ? mimes : null) + .build(); } - private static void populateBannerImps(List bannerImps, Price bidFloorPrice, Imp imp) { - if (imp.getBanner() != null) { - final Imp bannerImp = imp.toBuilder().video(null).xNative(null).audio(null).build(); - bannerImps.add(modifyImp(bannerImp, bidFloorPrice)); - } + private static boolean isValidSizeValue(Integer value) { + return value != null && value > 0; } - private static void populateVideoImps(List videoImps, Price bidFloorPrice, Imp imp) { - if (imp.getVideo() != null) { - final Imp videoImp = imp.toBuilder().banner(null).xNative(null).audio(null).build(); - videoImps.add(modifyImp(videoImp, bidFloorPrice)); - } + private static ResetDigitalRequest makeRequest(BidRequest request, ResetDigitalImp resetDigitalImp) { + return ResetDigitalRequest.builder() + .site(makeSite(request.getSite())) + .imps(Collections.singletonList(resetDigitalImp)) + .build(); } - private static void populateAudiImps(List audioImps, Price bidFloorPrice, Imp imp) { - if (imp.getAudio() != null) { - final Imp audioImp = imp.toBuilder().banner(null).xNative(null).video(null).build(); - audioImps.add(modifyImp(audioImp, bidFloorPrice)); + private static ResetDigitalSite makeSite(Site site) { + return site == null || ObjectUtils.allNull(site.getDomain(), site.getPage()) + ? null + : ResetDigitalSite.builder() + .domain(site.getDomain()) + .referrer(site.getPage()) + .build(); + } + + private static MultiMap makeHeaders(BidRequest request) { + final MultiMap headers = HttpUtil.headers(); + + final Device device = request.getDevice(); + if (device != null) { + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.ACCEPT_LANGUAGE_HEADER, device.getLanguage()); + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.USER_AGENT_HEADER, device.getUa()); + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_FORWARDED_FOR_HEADER, device.getIp()); + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_REAL_IP_HEADER, device.getIp()); + } + + final Site site = request.getSite(); + if (site != null) { + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.REFERER_HEADER, site.getPage()); } + + return headers; } @Override - public final Result> makeBids(BidderCall httpCall, BidRequest bidRequest) { + public Result> makeBids(BidderCall httpCall, BidRequest bidRequest) { try { - final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); - return Result.withValues(extractBids(bidResponse, httpCall.getRequest().getPayload())); + final ResetDigitalResponse bidResponse = mapper.decodeValue( + httpCall.getResponse().getBody(), + ResetDigitalResponse.class); + return Result.withValues(extractBids(bidRequest, bidResponse)); } catch (DecodeException | PreBidException e) { return Result.withError(BidderError.badServerResponse(e.getMessage())); } } - private static List extractBids(BidResponse bidResponse, BidRequest bidRequest) { - if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { - return Collections.emptyList(); + private static List extractBids(BidRequest bidRequest, ResetDigitalResponse bidResponse) { + final List bids = bidResponse == null + ? Collections.emptyList() + : CollectionUtils.emptyIfNull(bidResponse.getBids()).stream().filter(Objects::nonNull).toList(); + + if (bids.size() != 1) { + throw new PreBidException("expected exactly one bid in the response, but got %d".formatted(bids.size())); } - if (bidResponse.getCur() != null && !StringUtils.equalsIgnoreCase(DEFAULT_CURRENCY, bidResponse.getCur())) { - throw new PreBidException("Bidder support only USD currency"); + + final ResetDigitalBid bid = bids.getFirst(); + final Imp correspondingImp = bidRequest.getImp().stream() + .filter(imp -> Objects.equals(imp.getId(), bid.getImpId())) + .findFirst() + .orElseThrow(() -> new PreBidException( + "no matching impression found for ImpID %s".formatted(bid.getImpId()))); + + return Collections.singletonList( + BidderBid.of(makeBid(bid), resolveBidType(correspondingImp), bid.getSeat(), BID_CURRENCY)); + } + + private static Bid makeBid(ResetDigitalBid bid) { + try { + return Bid.builder() + .id(bid.getBidId()) + .price(bid.getCpm()) + .impid(bid.getImpId()) + .cid(bid.getCid()) + .crid(bid.getCrid()) + .adm(bid.getHtml()) + .w(Integer.parseInt(bid.getW())) + .h(Integer.parseInt(bid.getH())) + .build(); + } catch (NumberFormatException e) { + throw new PreBidException(e.getMessage()); } - return bidsFromResponse(bidResponse, bidRequest); - } - - private static List bidsFromResponse(BidResponse bidResponse, BidRequest bidRequest) { - return bidResponse.getSeatbid().stream() - .filter(Objects::nonNull) - .map(SeatBid::getBid) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getBidType(bid, bidRequest.getImp()), DEFAULT_CURRENCY)) - .toList(); - } - - private static BidType getBidType(Bid bid, List imps) { - final String impId = bid.getImpid(); - for (Imp imp : imps) { - if (imp.getId().equals(impId)) { - if (imp.getBanner() != null) { - return BidType.banner; - } else if (imp.getVideo() != null) { - return BidType.video; - } else if (imp.getAudio() != null) { - return BidType.audio; - } - } + } + + private static BidType resolveBidType(Imp imp) throws PreBidException { + if (imp.getVideo() != null) { + return BidType.video; + } else if (imp.getAudio() != null) { + return BidType.audio; + } else { + return BidType.banner; } - throw new PreBidException("Failed to find banner/video/audio impression " + impId); } } diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImp.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImp.java new file mode 100644 index 00000000000..5674c2446a7 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImp.java @@ -0,0 +1,19 @@ +package org.prebid.server.bidder.resetdigital.request; + +import lombok.Builder; +import lombok.Value; + +@Value +@Builder +public class ResetDigitalImp { + + ResetDigitalImpZone zoneId; + + String bidId; + + String impId; + + ResetDigitalImpMediaTypes mediaTypes; + + ResetDigitalImpExt ext; +} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpExt.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpExt.java new file mode 100644 index 00000000000..16363a5e6d9 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpExt.java @@ -0,0 +1,9 @@ +package org.prebid.server.bidder.resetdigital.request; + +import lombok.Value; + +@Value(staticConstructor = "of") +public class ResetDigitalImpExt { + + String gpid; +} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaType.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaType.java new file mode 100644 index 00000000000..5ee15918c38 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaType.java @@ -0,0 +1,15 @@ +package org.prebid.server.bidder.resetdigital.request; + +import lombok.Builder; +import lombok.Value; + +import java.util.List; + +@Value(staticConstructor = "of") +@Builder +public class ResetDigitalImpMediaType { + + List> sizes; + + List mimes; +} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaTypes.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaTypes.java new file mode 100644 index 00000000000..7483f318e0e --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaTypes.java @@ -0,0 +1,27 @@ +package org.prebid.server.bidder.resetdigital.request; + +import lombok.Builder; +import lombok.Value; + +@Value(staticConstructor = "of") +@Builder +public class ResetDigitalImpMediaTypes { + + ResetDigitalImpMediaType banner; + + ResetDigitalImpMediaType video; + + ResetDigitalImpMediaType audio; + + public static ResetDigitalImpMediaTypes banner(ResetDigitalImpMediaType banner) { + return ResetDigitalImpMediaTypes.builder().banner(banner).build(); + } + + public static ResetDigitalImpMediaTypes video(ResetDigitalImpMediaType video) { + return ResetDigitalImpMediaTypes.builder().video(video).build(); + } + + public static ResetDigitalImpMediaTypes audio(ResetDigitalImpMediaType audio) { + return ResetDigitalImpMediaTypes.builder().audio(audio).build(); + } +} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpZone.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpZone.java new file mode 100644 index 00000000000..516ee7ec8bd --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpZone.java @@ -0,0 +1,11 @@ +package org.prebid.server.bidder.resetdigital.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Value; + +@Value(staticConstructor = "of") +public class ResetDigitalImpZone { + + @JsonProperty("placementId") + String placementId; +} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalRequest.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalRequest.java new file mode 100644 index 00000000000..8294ec1a469 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalRequest.java @@ -0,0 +1,15 @@ +package org.prebid.server.bidder.resetdigital.request; + +import lombok.Builder; +import lombok.Value; + +import java.util.List; + +@Value +@Builder +public class ResetDigitalRequest { + + ResetDigitalSite site; + + List imps; +} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalSite.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalSite.java new file mode 100644 index 00000000000..77962b232b2 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalSite.java @@ -0,0 +1,13 @@ +package org.prebid.server.bidder.resetdigital.request; + +import lombok.Builder; +import lombok.Value; + +@Value +@Builder +public class ResetDigitalSite { + + String domain; + + String referrer; +} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalBid.java b/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalBid.java new file mode 100644 index 00000000000..fead0572112 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalBid.java @@ -0,0 +1,31 @@ +package org.prebid.server.bidder.resetdigital.response; + +import lombok.Builder; +import lombok.Value; + +import java.math.BigDecimal; + +@Value(staticConstructor = "of") +@Builder +public class ResetDigitalBid { + + String bidId; + + String impId; + + BigDecimal cpm; + + String cid; + + String crid; + + String adid; + + String w; + + String h; + + String seat; + + String html; +} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalResponse.java b/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalResponse.java new file mode 100644 index 00000000000..2dcf57e8d80 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalResponse.java @@ -0,0 +1,11 @@ +package org.prebid.server.bidder.resetdigital.response; + +import lombok.Value; + +import java.util.List; + +@Value(staticConstructor = "of") +public class ResetDigitalResponse { + + List bids; +} diff --git a/src/main/java/org/prebid/server/bidder/vungle/VungleBidder.java b/src/main/java/org/prebid/server/bidder/vungle/VungleBidder.java index f2c87bc2583..aa16a4367f1 100644 --- a/src/main/java/org/prebid/server/bidder/vungle/VungleBidder.java +++ b/src/main/java/org/prebid/server/bidder/vungle/VungleBidder.java @@ -7,7 +7,6 @@ import com.iab.openrtb.request.Site; import com.iab.openrtb.request.User; import com.iab.openrtb.response.BidResponse; -import com.iab.openrtb.response.SeatBid; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpMethod; import org.apache.commons.collections4.CollectionUtils; @@ -32,7 +31,6 @@ import java.math.BigDecimal; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -165,10 +163,9 @@ private static List extractBids(BidResponse bidResponse) { private static List bidsFromResponse(BidResponse bidResponse) { return bidResponse.getSeatbid().stream() .filter(Objects::nonNull) - .map(SeatBid::getBid) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, BidType.video, bidResponse.getCur())) + .flatMap(seatBid -> seatBid.getBid().stream() + .filter(Objects::nonNull) + .map(bid -> BidderBid.of(bid, BidType.video, seatBid.getSeat(), bidResponse.getCur()))) .toList(); } } diff --git a/src/main/java/org/prebid/server/metric/MetricName.java b/src/main/java/org/prebid/server/metric/MetricName.java index 7c41dd65e72..84bb68f1c67 100644 --- a/src/main/java/org/prebid/server/metric/MetricName.java +++ b/src/main/java/org/prebid/server/metric/MetricName.java @@ -75,6 +75,7 @@ public enum MetricName { err, networkerr, buyeruid_scrubbed, + seat, // bids validation warn, diff --git a/src/main/java/org/prebid/server/metric/Metrics.java b/src/main/java/org/prebid/server/metric/Metrics.java index 2d0cc1aeaf2..0fb0145f313 100644 --- a/src/main/java/org/prebid/server/metric/Metrics.java +++ b/src/main/java/org/prebid/server/metric/Metrics.java @@ -382,6 +382,10 @@ public void updateSecureValidationMetrics(String bidder, String accountId, Metri forAccount(accountId).response().validation().secure().incCounter(type); } + public void updateSeatValidationMetrics(String bidder) { + forAdapter(bidder).response().validation().incCounter(MetricName.seat); + } + public void updateUserSyncOptoutMetric() { userSync().incCounter(MetricName.opt_outs); } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/resetdigital/ExtImpResetDigital.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/resetdigital/ExtImpResetDigital.java new file mode 100644 index 00000000000..78cf004662e --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/resetdigital/ExtImpResetDigital.java @@ -0,0 +1,9 @@ +package org.prebid.server.proto.openrtb.ext.request.resetdigital; + +import lombok.Value; + +@Value(staticConstructor = "of") +public class ExtImpResetDigital { + + String placementId; +} diff --git a/src/main/java/org/prebid/server/settings/model/Account.java b/src/main/java/org/prebid/server/settings/model/Account.java index c54998320d4..3224b0e7a48 100644 --- a/src/main/java/org/prebid/server/settings/model/Account.java +++ b/src/main/java/org/prebid/server/settings/model/Account.java @@ -27,6 +27,9 @@ public class Account { AccountSettings settings; + @JsonAlias("alternatebiddercodes") + AccountAlternateBidderCodes alternateBidderCodes; + public static Account empty(String id) { return Account.builder().id(id).build(); } diff --git a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java new file mode 100644 index 00000000000..ffbebc0d5c6 --- /dev/null +++ b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java @@ -0,0 +1,15 @@ +package org.prebid.server.settings.model; + +import lombok.Builder; +import lombok.Value; + +import java.util.Map; + +@Builder(toBuilder = true) +@Value +public class AccountAlternateBidderCodes { + + Boolean enabled; + + Map bidders; +} diff --git a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java new file mode 100644 index 00000000000..dea69c17da1 --- /dev/null +++ b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java @@ -0,0 +1,17 @@ +package org.prebid.server.settings.model; + +import com.fasterxml.jackson.annotation.JsonAlias; +import lombok.Builder; +import lombok.Value; + +import java.util.Set; + +@Builder(toBuilder = true) +@Value +public class AccountAlternateBidderCodesBidder { + + Boolean enabled; + + @JsonAlias("allowedbiddercodes") + Set allowedBidderCodes; +} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ResetDigitalConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ResetDigitalConfiguration.java index 4e4de161f66..33823866d5f 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ResetDigitalConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ResetDigitalConfiguration.java @@ -2,7 +2,6 @@ import org.prebid.server.bidder.BidderDeps; import org.prebid.server.bidder.resetdigital.ResetDigitalBidder; -import org.prebid.server.currency.CurrencyConversionService; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; @@ -31,16 +30,12 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps resetDigitalBidderDeps(BidderConfigurationProperties resetDigitalConfigurationProperties, @NotBlank @Value("${external-url}") String externalUrl, - CurrencyConversionService currencyConversionService, JacksonMapper mapper) { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(resetDigitalConfigurationProperties) .usersyncerCreator(UsersyncerCreator.create(externalUrl)) - .bidderCreator(config -> new ResetDigitalBidder( - config.getEndpoint(), - currencyConversionService, - mapper)) + .bidderCreator(config -> new ResetDigitalBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/util/BidderUtil.java b/src/main/java/org/prebid/server/util/BidderUtil.java index d6869e3b72d..0895815670c 100644 --- a/src/main/java/org/prebid/server/util/BidderUtil.java +++ b/src/main/java/org/prebid/server/util/BidderUtil.java @@ -33,6 +33,21 @@ public static HttpRequest defaultRequest(BidRequest bidRequest, return defaultRequest(bidRequest, HttpUtil.headers(), endpointUrl, mapper); } + public static HttpRequest defaultRequest(T bidRequest, + String endpointUrl, + Set impIds, + JacksonMapper mapper) { + + return HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(HttpUtil.headers()) + .impIds(impIds) + .body(mapper.encodeToBytes(bidRequest)) + .payload(bidRequest) + .build(); + } + public static HttpRequest defaultRequest(BidRequest bidRequest, MultiMap headers, String endpointUrl, @@ -47,6 +62,22 @@ public static HttpRequest defaultRequest(BidRequest bidRequest, .build(); } + public static HttpRequest defaultRequest(T bidRequest, + MultiMap headers, + String endpointUrl, + Set impIds, + JacksonMapper mapper) { + + return HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(headers) + .impIds(impIds) + .body(mapper.encodeToBytes(bidRequest)) + .payload(bidRequest) + .build(); + } + public static Set impIds(BidRequest bidRequest) { return bidRequest.getImp().stream() .map(Imp::getId) diff --git a/src/main/java/org/prebid/server/validation/RequestValidator.java b/src/main/java/org/prebid/server/validation/RequestValidator.java index d4838b1a5e3..cf8a1dd2745 100644 --- a/src/main/java/org/prebid/server/validation/RequestValidator.java +++ b/src/main/java/org/prebid/server/validation/RequestValidator.java @@ -248,11 +248,6 @@ private void validateBidAdjustmentFactors(ExtRequestBidAdjustmentFactors adjustm for (Map.Entry bidderAdjustment : bidderAdjustments.entrySet()) { final String bidder = bidderAdjustment.getKey(); - if (isUnknownBidderOrAlias(bidder, aliases)) { - throw new ValidationException( - "request.ext.prebid.bidadjustmentfactors.%s is not a known bidder or alias", bidder); - } - final BigDecimal adjustmentFactor = bidderAdjustment.getValue(); if (adjustmentFactor.compareTo(BigDecimal.ZERO) <= 0) { throw new ValidationException( @@ -271,23 +266,17 @@ private void validateBidAdjustmentFactors(ExtRequestBidAdjustmentFactors adjustm for (Map.Entry> entry : adjustmentsMediaTypeFactors.entrySet()) { - validateBidAdjustmentFactorsByMediatype(entry.getKey(), entry.getValue(), aliases); + validateBidAdjustmentFactorsByMediatype(entry.getKey(), entry.getValue()); } } private void validateBidAdjustmentFactorsByMediatype(ImpMediaType mediaType, - Map bidderAdjustments, - Map aliases) throws ValidationException { + Map bidderAdjustments) + throws ValidationException { for (Map.Entry bidderAdjustment : bidderAdjustments.entrySet()) { final String bidder = bidderAdjustment.getKey(); - if (isUnknownBidderOrAlias(bidder, aliases)) { - throw new ValidationException( - "request.ext.prebid.bidadjustmentfactors.%s.%s is not a known bidder or alias", - mediaType, bidder); - } - final BigDecimal adjustmentFactor = bidderAdjustment.getValue(); if (adjustmentFactor.compareTo(BigDecimal.ZERO) <= 0) { throw new ValidationException( diff --git a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java index 4e2f062218b..585175a9a82 100644 --- a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java +++ b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java @@ -7,6 +7,7 @@ import com.iab.openrtb.request.Site; import com.iab.openrtb.response.Bid; import org.apache.commons.collections4.ListUtils; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.auction.BidderAliases; @@ -21,6 +22,8 @@ import org.prebid.server.metric.Metrics; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountAlternateBidderCodes; +import org.prebid.server.settings.model.AccountAlternateBidderCodesBidder; import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.settings.model.AccountBidValidationConfig; import org.prebid.server.settings.model.BidValidationEnforcement; @@ -31,6 +34,8 @@ import java.util.Currency; import java.util.List; import java.util.Objects; +import java.util.Optional; +import java.util.Set; import java.util.function.Consumer; /** @@ -39,14 +44,22 @@ public class ResponseBidValidator { private static final Logger logger = LoggerFactory.getLogger(ResponseBidValidator.class); - private static final ConditionalLogger UNRELATED_BID_LOGGER = new ConditionalLogger("not_matched_bid", logger); - private static final ConditionalLogger SECURE_CREATIVE_LOGGER = new ConditionalLogger("secure_creatives_validation", + private static final ConditionalLogger UNRELATED_BID_LOGGER = new ConditionalLogger( + "not_matched_bid", logger); - private static final ConditionalLogger CREATIVE_SIZE_LOGGER = new ConditionalLogger("creative_size_validation", + private static final ConditionalLogger SECURE_CREATIVE_LOGGER = new ConditionalLogger( + "secure_creatives_validation", + logger); + private static final ConditionalLogger CREATIVE_SIZE_LOGGER = new ConditionalLogger( + "creative_size_validation", + logger); + private static final ConditionalLogger ALTERNATE_BIDDER_CODE_LOGGER = new ConditionalLogger( + "alternate_bidder_code_validation", logger); private static final String[] INSECURE_MARKUP_MARKERS = {"http:", "http%3A"}; private static final String[] SECURE_MARKUP_MARKERS = {"https:", "https%3A"}; + private static final String ALTERNATE_BIDDER_CODE_WILDCARD = "*"; private final BidValidationEnforcement bannerMaxSizeEnforcement; private final BidValidationEnforcement secureMarkupEnforcement; @@ -81,6 +94,7 @@ public ValidationResult validate(BidderBid bidderBid, validateCommonFields(bid); validateTypeSpecific(bidderBid, bidder); validateCurrency(bidderBid.getBidCurrency()); + validateSeat(bidderBid, bidder, account, bidRejectionTracker, warnings); final Imp correspondingImp = findCorrespondingImp(bid, bidRequest); if (bidderBid.getType() == BidType.banner) { @@ -148,6 +162,59 @@ private static void validateCurrency(String currency) throws ValidationException } } + private void validateSeat(BidderBid bid, + String bidder, + Account account, + BidRejectionTracker bidRejectionTracker, + List warnings) { + + if (bid.getSeat() == null || StringUtils.equals(bid.getSeat(), bidder)) { + return; + } + + final AccountAlternateBidderCodesBidder alternateBidder = resolveAlternateBidder(bidder, account); + if (!isAlternateBidderCodesEnabled(account) || alternateBidder == null) { + warnings.add(rejectBidOnInvalidSeat(bid, bidder, account, bidRejectionTracker)); + return; + } + + final Set allowedBidderCodes = ObjectUtils.defaultIfNull( + alternateBidder.getAllowedBidderCodes(), + Collections.singleton(ALTERNATE_BIDDER_CODE_WILDCARD)); + + if (!allowedBidderCodes.contains(ALTERNATE_BIDDER_CODE_WILDCARD) + && !allowedBidderCodes.contains(bid.getSeat())) { + warnings.add(rejectBidOnInvalidSeat(bid, bidder, account, bidRejectionTracker)); + } + } + + private static Boolean isAlternateBidderCodesEnabled(Account account) { + return Optional.ofNullable(account.getAlternateBidderCodes()) + .map(AccountAlternateBidderCodes::getEnabled) + .orElse(false); + } + + private static AccountAlternateBidderCodesBidder resolveAlternateBidder(String bidder, Account account) { + return Optional.ofNullable(account.getAlternateBidderCodes()) + .map(AccountAlternateBidderCodes::getBidders) + .map(bidders -> bidders.get(bidder)) + .filter(alternate -> BooleanUtils.isTrue(alternate.getEnabled())) + .orElse(null); + } + + private String rejectBidOnInvalidSeat(BidderBid bid, + String bidder, + Account account, + BidRejectionTracker bidRejectionTracker) { + + final String message = "invalid bidder code %s was set by the adapter %s for the account %s" + .formatted(bid.getSeat(), bidder, account.getId()); + bidRejectionTracker.rejectBid(bid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); + metrics.updateSeatValidationMetrics(bidder); + ALTERNATE_BIDDER_CODE_LOGGER.warn(message, logSamplingRate); + return message; + } + private Imp findCorrespondingImp(Bid bid, BidRequest bidRequest) throws ValidationException { return bidRequest.getImp().stream() .filter(imp -> Objects.equals(imp.getId(), bid.getImpid())) diff --git a/src/main/resources/bidder-config/resetdigital.yaml b/src/main/resources/bidder-config/resetdigital.yaml index 885916d0d8d..3ae9e26bf3e 100644 --- a/src/main/resources/bidder-config/resetdigital.yaml +++ b/src/main/resources/bidder-config/resetdigital.yaml @@ -4,9 +4,6 @@ adapters: meta-info: maintainer-email: biddersupport@resetdigital.co app-media-types: - - banner - - video - - audio site-media-types: - banner - video @@ -16,6 +13,6 @@ adapters: usersync: cookie-family-name: resetdigital redirect: - url: https://sync.resetdigital.co/csync?pid=rubicon&redir={{redirect_url}} + url: https://sync.resetdigital.co/csync?redir={{redirect_url}} support-cors: false uid-macro: '$USER_ID' diff --git a/src/main/resources/static/bidder-params/resetdigital.json b/src/main/resources/static/bidder-params/resetdigital.json index 3710cfbc598..07a7bc2b551 100644 --- a/src/main/resources/static/bidder-params/resetdigital.json +++ b/src/main/resources/static/bidder-params/resetdigital.json @@ -1,23 +1,13 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "ResetDigital Adapter Params", - "description": "A schema which validates params accepted by the ResetDigital adapter", + "title": "Reset Digital Adapter Params", + "description": "A schema which validates params accepted by the Reset Digital adapter", "type": "object", "properties": { - "pubId": { + "placement_id": { "type": "string", - "description": "The publisher's ID provided" - }, - "zoneId": { - "type": "string", - "description": "Zone ID" - }, - "forceBid": { - "type": "boolean", - "description": "Force bids with a test creative" + "minLength": 1, + "description": "Placement ID for the Reset Digital ad unit. This is the identifier for the ad unit on the Reset Digital platform, and its optional" } - }, - "required": [ - "pubId" - ] + } } diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index 04b7d279956..07d695d0989 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -283,7 +283,7 @@ public void shouldPassBidWithGeneratedIdAndPreserveExtFieldsWhenIdGeneratorTypeU .build(); final String bidder = "bidder1"; final List bidderResponses = singletonList( - BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(imp), @@ -306,7 +306,7 @@ public void shouldPassBidWithGeneratedIdAndPreserveExtFieldsWhenIdGeneratorTypeU .put("origbidcur", "test") .set("prebid", mapper.valueToTree(extBidPrebid))) .build(); - final BidInfo bidInfo = toBidInfo(expectedBid, imp, bidder, banner, true); + final BidInfo bidInfo = toBidInfo(expectedBid, imp, bidder, "seat", banner, true); verify(coreCacheService).cacheBidsOpenrtb(eq(singletonList(bidInfo)), any(), any(), any()); } @@ -322,7 +322,7 @@ public void shouldSkipBidderWhenRejectedByProcessedBidderResponseHooks() { .price(BigDecimal.valueOf(5.67)) .build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -348,6 +348,7 @@ public void shouldPassRequestModifiedByBidderRequestHooks() { .price(BigDecimal.valueOf(1.23)) .build(), video, + "seat", "EUR")))))) .when(hookStageExecutor).executeProcessedBidderResponseStage(any(), any()); @@ -357,7 +358,7 @@ public void shouldPassRequestModifiedByBidderRequestHooks() { .price(BigDecimal.valueOf(5.67)) .build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -382,7 +383,7 @@ public void shouldPassOriginalTimeoutToCacheServiceIfCachingIsRequested() { .price(BigDecimal.valueOf(5.67)) .build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -620,7 +621,7 @@ public void shouldModifyBidAdmWhenBidVideoAndVastModifierReturnValue() { final String bidder = "bidder1"; final List bidderResponses = singletonList( - BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, video, "USD")), 100)); + BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, video, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -745,7 +746,7 @@ public void shouldSetNbrNullAndPopulateSeatbidWhenAtLeastOneBidIsPresent() { // given final Bid bid = Bid.builder().impid(IMP_ID).id("bidId").build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, null)), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", null)), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -767,7 +768,7 @@ public void shouldSkipBidderResponsesWhereSeatBidContainEmptyBids() { final Bid bid = Bid.builder().impid(IMP_ID).id("bidId").build(); final List bidderResponses = asList( BidderResponse.of("bidder1", givenSeatBid(), 0), - BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(bid, banner, "USD")), 0)); + BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 0)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -792,7 +793,7 @@ public void shouldOverrideBidIdWhenIdGeneratorIsUUID() { .set("prebid", mapper.valueToTree(ExtBidPrebid.builder().type(banner).build()))) .build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(bid, banner, "USD")), 0)); + BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 0)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -845,7 +846,7 @@ public void shouldUseGeneratedBidIdForEventAndCacheWhenIdGeneratorIsUUIDAndEvent final String bidder = "bidder1"; final List bidderResponses = singletonList( - BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, banner, "USD")), 0)); + BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 0)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -876,7 +877,7 @@ public void shouldUseGeneratedBidIdForEventAndCacheWhenIdGeneratorIsUUIDAndEvent .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(extBidPrebid))) .build(); - final BidInfo expectedBidInfo = toBidInfo(expectedBid, imp, bidder, banner, true); + final BidInfo expectedBidInfo = toBidInfo(expectedBid, imp, bidder, "seat", banner, true); verify(coreCacheService).cacheBidsOpenrtb(eq(singletonList(expectedBidInfo)), any(), any(), any()); verify(eventsService).createEvent(eq(generatedBidId), anyString(), anyString(), anyBoolean(), any()); @@ -899,7 +900,7 @@ public void shouldSetExpectedResponseSeatBidAndBidFields() { final String bidder = "bidder1"; final List bidderResponses = singletonList(BidderResponse.of(bidder, - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -925,7 +926,7 @@ public void shouldSetExpectedResponseSeatBidAndBidFields() { assertThat(bidResponse.getSeatbid()) .containsOnly(SeatBid.builder() - .seat(bidder) + .seat("seat") .group(0) .bid(singletonList(Bid.builder() .id("bidId") @@ -945,7 +946,7 @@ public void shouldUpdateCacheDebugLogWithExtBidResponseWhenEnabledAndBidsReturne final Bid bid = Bid.builder().id("bidId").price(BigDecimal.ONE).adm("adm").impid("i1") .ext(mapper.valueToTree(singletonMap("bidExt", 1))).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -999,7 +1000,9 @@ public void shouldUseBidsReturnedInCategoryMapperResultAndUpdateErrors() { given(categoryMappingService.createCategoryMapping(any(), any(), any())) .willReturn(Future.succeededFuture(CategoryMappingResult.of(emptyMap(), emptyMap(), - singletonList(BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid1, banner, "USD")), + singletonList(BidderResponse.of( + "bidder1", + givenSeatBid(BidderBid.of(bid1, banner, "seat", "USD")), 100)), singletonList("Filtered bid 2")))); @@ -1020,7 +1023,7 @@ public void shouldThrowExceptionWhenCategoryMappingThrowsPrebidException() { // given final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(identity(), identity(), givenImp()), @@ -1056,7 +1059,7 @@ public void shouldNotWriteSkadnAttributeToBidderSection() { final String bidder = "bidder1"; final List bidderResponses = singletonList(BidderResponse.of(bidder, - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -1118,7 +1121,7 @@ public void shouldAddTypeToNativeBidAdm() throws JsonProcessingException { .adm(mapper.writeValueAsString(responseAdm)) .ext(mapper.valueToTree(singletonMap("bidExt", 1))).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, xNative, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -1179,7 +1182,7 @@ public void shouldReturnEmptyAssetIfImageTypeIsEmpty() throws JsonProcessingExce .ext(mapper.valueToTree(singletonMap("bidExt", 1))) .build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, xNative, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -1234,7 +1237,7 @@ public void shouldReturnEmptyAssetIfNoRelatedNativeAssetFound() throws JsonProce .ext(mapper.valueToTree(singletonMap("bidExt", 1))) .build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, xNative, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -1293,7 +1296,7 @@ public void shouldReturnEmptyAssetIfIdIsNotPresentRelatedNativeAssetFound() thro .ext(mapper.valueToTree(singletonMap("bidExt", 1))) .build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, xNative, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -1351,7 +1354,7 @@ public void shouldReturnEmptyAssetIfDataTypeIsEmpty() throws JsonProcessingExcep .ext(mapper.valueToTree(singletonMap("bidExt", 1))) .build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, xNative, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -1379,7 +1382,7 @@ public void shouldSetBidAdmToNullIfCacheIdIsPresentAndReturnCreativeBidsIsFalse( .impid(IMP_ID) .build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1409,7 +1412,7 @@ public void shouldSetBidAdmToNullIfVideoCacheIdIsPresentAndReturnCreativeVideoBi // given final Bid bid = Bid.builder().price(BigDecimal.ONE).adm(BID_ADM).id("bidId").impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1439,7 +1442,7 @@ public void shouldSetBidExpWhenCacheIdIsMatched() { // given final Bid bid = Bid.builder().price(BigDecimal.ONE).impid(IMP_ID).id("bidId").build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1469,7 +1472,7 @@ public void shouldSetBidExpMaxTtlWhenCacheIdIsMatchedAndBothTtlIsSet() { // given final Bid bid = Bid.builder().price(BigDecimal.ONE).impid(IMP_ID).id("bidId").build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1499,7 +1502,7 @@ public void shouldTolerateMissingExtInSeatBidAndBid() { // given final Bid bid = Bid.builder().id("bidId").price(BigDecimal.ONE).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -1528,7 +1531,7 @@ public void shouldPassPreferDealsToWinningComparatorFactoryWhenBidRequestTrue() // given final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid("i1").build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1548,7 +1551,7 @@ public void shouldPassPreferDealsFalseWhenBidRequestPreferDealsIsNotDefined() { // given final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid("i1").build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1568,7 +1571,7 @@ public void shouldPopulateTargetingKeywords() { // given final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1602,7 +1605,7 @@ public void shouldPopulateTargetingKeywordsForAmpRequest() { // given final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1638,7 +1641,7 @@ public void shouldTruncateTargetingKeywordsByGlobalConfig() { // given final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("someVeryLongBidderName", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1698,7 +1701,7 @@ public void shouldTruncateTargetingKeywordsByAccountConfig() { final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("someVeryLongBidderName", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -1747,7 +1750,7 @@ public void shouldTruncateTargetingKeywordsByRequestPassedValue() { final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("someVeryLongBidderName", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -1786,11 +1789,11 @@ public void shouldReduceAndNotPopulateTargetingKeywordsForExtraBidsWhenCodePrefi final List bidderResponses = singletonList( BidderResponse.of(bidder1, givenSeatBid( - BidderBid.of(bidder1Bid1, banner, null), // extra bid - BidderBid.of(bidder1Bid2, banner, null), // extra bid - BidderBid.of(bidder1Bid3, banner, null), // Will be removed by price - BidderBid.of(bidder1Bid4, banner, null), - BidderBid.of(bidder1Bid5, banner, null)), + BidderBid.of(bidder1Bid1, banner, "seat", null), // extra bid + BidderBid.of(bidder1Bid2, banner, "seat", null), // extra bid + BidderBid.of(bidder1Bid3, banner, "seat", null), // Will be removed by price + BidderBid.of(bidder1Bid4, banner, "seat", null), + BidderBid.of(bidder1Bid5, banner, "seat", null)), 100)); final AuctionContext auctionContext = givenAuctionContext( @@ -1845,9 +1848,9 @@ public void shouldNotPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIsDefine final List bidderResponses = singletonList( BidderResponse.of(bidder1, givenSeatBid( - BidderBid.of(bidder1Bid1, banner, null), // extra bid - BidderBid.of(bidder1Bid2, banner, null), // extra bid - BidderBid.of(bidder1Bid3, banner, null)), + BidderBid.of(bidder1Bid1, banner, "seat", null), // extra bid + BidderBid.of(bidder1Bid2, banner, "seat", null), // extra bid + BidderBid.of(bidder1Bid3, banner, "seat", null)), 100)); final AuctionContext auctionContext = givenAuctionContext( @@ -1890,11 +1893,11 @@ public void shouldReduceAndPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIs final List bidderResponses = singletonList( BidderResponse.of(bidder1, givenSeatBid( - BidderBid.of(bidder1Bid1, banner, null), // extra bid - BidderBid.of(bidder1Bid2, banner, null), // extra bid - BidderBid.of(bidder1Bid3, banner, null), // Will be removed by price - BidderBid.of(bidder1Bid4, banner, null), - BidderBid.of(bidder1Bid5, banner, null)), + BidderBid.of(bidder1Bid1, banner, "seat", null), // extra bid + BidderBid.of(bidder1Bid2, banner, "seat", null), // extra bid + BidderBid.of(bidder1Bid3, banner, "seat", null), // Will be removed by price + BidderBid.of(bidder1Bid4, banner, "seat", null), + BidderBid.of(bidder1Bid5, banner, "seat", null)), 100)); final AuctionContext auctionContext = givenAuctionContext( @@ -1953,10 +1956,10 @@ public void shouldPopulateTargetingKeywordsForWinningBidsAndWinningBidsByBidder( final List bidderResponses = asList( BidderResponse.of("bidder1", givenSeatBid( - BidderBid.of(firstBid, banner, null), - BidderBid.of(secondBid, banner, null)), 100), + BidderBid.of(firstBid, banner, "seat", null), + BidderBid.of(secondBid, banner, "seat", null)), 100), BidderResponse.of("bidder2", - givenSeatBid(BidderBid.of(thirdBid, banner, null)), 111)); + givenSeatBid(BidderBid.of(thirdBid, banner, "seat", null)), 111)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -2007,7 +2010,7 @@ public void shouldPopulateTargetingKeywordsFromMediaTypePriceGranularities() { final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -2039,7 +2042,7 @@ public void shouldPopulateCacheIdHostPathAndUuidTargetingKeywords() { // given final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -2091,7 +2094,7 @@ public void shouldPopulateTargetingKeywordsWithAdditionalValuesFromRequest() { final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of( - "bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + "bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -2114,7 +2117,7 @@ public void shouldPopulateTargetingKeywordsIfBidWasCachedAndAdmWasRemoved() { // given final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).adm(BID_ADM).build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -2163,7 +2166,7 @@ public void shouldAddExtPrebidEventsIfEventsAreEnabledAndExtRequestPrebidEventPr .impid(IMP_ID) .build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -2220,7 +2223,7 @@ public void shouldAddExtPrebidEventsIfEventsAreEnabledAndAccountSupportEventsFor .impid(IMP_ID) .build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -2270,7 +2273,7 @@ public void shouldAddExtPrebidEventsIfEventsAreEnabledAndDefaultAccountAnalytics .impid(IMP_ID) .build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -2306,7 +2309,7 @@ public void shouldAddExtPrebidVideoToExtBidPrebidWhenVideoBids() { .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(extBidPrebid))) .build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -2339,7 +2342,7 @@ public void shouldAddDealTierSatisfiedToExtBidPrebidWhenBidsPrioritySatisfiedMin .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree( ExtBidPrebid.builder().video(ExtBidPrebidVideo.of(1, "category")).build()))).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(Imp.builder().id("i1").build()), @@ -2375,7 +2378,7 @@ public void shouldNotAddExtPrebidEventsIfEventsAreNotEnabled() { final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -2412,7 +2415,7 @@ public void shouldNotAddExtPrebidEventsIfExtRequestPrebidEventsNull() { .impid(IMP_ID) .build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp()), @@ -2453,7 +2456,7 @@ public void shouldNotAddExtPrebidEventsIfAccountDoesNotSupportEventsForChannel() .impid(IMP_ID) .build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -2476,7 +2479,7 @@ public void shouldReturnCacheEntityInExt() { // given final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() .doCaching(true) @@ -2525,7 +2528,7 @@ public void shouldNotPopulateWinningBidTargetingIfIncludeWinnersFlagIsFalse() { final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -2571,7 +2574,7 @@ public void shouldNotPopulateBidderKeysTargetingIfIncludeBidderKeysFlagIsFalse() final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -2612,8 +2615,8 @@ public void shouldNotPopulateCacheIdTargetingKeywordsIfBidCpmIsZero() { final Bid secondBid = Bid.builder().id("bidId2").impid("impId2").price(BigDecimal.valueOf(5.67)).build(); final List bidderResponses = asList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(firstBid, banner, null)), 99), - BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(secondBid, banner, null)), 123)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(firstBid, banner, "seat", null)), 99), + BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(secondBid, banner, "seat", null)), 123)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -2685,7 +2688,7 @@ public void shouldPopulateBidResponseExtension() { final List bidderResponses = singletonList(BidderResponse.of( "bidder1", BidderSeatBid.builder() - .bids(singletonList(BidderBid.of(bid, xNative, null))) + .bids(singletonList(BidderBid.of(bid, xNative, "seat", null))) .errors(singletonList(BidderError.badInput("bad_input"))) .warnings(singletonList(BidderError.generic("some_warning"))) .build(), @@ -2735,7 +2738,7 @@ public void shouldPopulateBidExpBasedOnCachedResult() { final Imp imp = Imp.builder().id("impId").exp(20).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -2806,7 +2809,7 @@ public void impToStoredVideoJsonShouldTolerateWhenStoredVideoFetchIsFailed() { final Bid bid = Bid.builder().id("bidId1").impid(IMP_ID).price(BigDecimal.valueOf(5.67)).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(imp), @@ -2855,9 +2858,9 @@ public void impToStoredVideoJsonShouldInjectStoredVideoWhenExtOptionsIsTrueAndVi final Bid bid2 = Bid.builder().id("bidId2").impid("impId2").price(BigDecimal.valueOf(2)).build(); final Bid bid3 = Bid.builder().id("bidId3").impid("impId3").price(BigDecimal.valueOf(3)).build(); final List bidderBids = mutableList( - BidderBid.of(bid1, banner, "USD"), - BidderBid.of(bid2, banner, "USD"), - BidderBid.of(bid3, banner, "USD")); + BidderBid.of(bid1, banner, "seat", "USD"), + BidderBid.of(bid2, banner, "seat", "USD"), + BidderBid.of(bid3, banner, "seat", "USD")); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.of(bidderBids), 100)); @@ -2906,7 +2909,7 @@ public void impToStoredVideoJsonShouldAddErrorsWithPrebidBidderWhenStoredVideoRe final BidRequest bidRequest = givenBidRequest(imp1); final Bid bid1 = Bid.builder().id("bidId1").impid(IMP_ID).price(BigDecimal.valueOf(5.67)).build(); - final List bidderBids = singletonList(BidderBid.of(bid1, banner, "USD")); + final List bidderBids = singletonList(BidderBid.of(bid1, banner, "seat", "USD")); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.of(bidderBids), 100)); @@ -2977,7 +2980,7 @@ public void shouldProcessRequestAndAddErrorAboutDeprecatedBidder() { public void shouldProcessRequestAndAddErrorFromAuctionContext() { // given final Bid bid1 = Bid.builder().id("bidId1").impid(IMP_ID).price(BigDecimal.valueOf(5.67)).build(); - final List bidderBids = singletonList(BidderBid.of(bid1, banner, "USD")); + final List bidderBids = singletonList(BidderBid.of(bid1, banner, "seat", "USD")); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.of(bidderBids), 100)); @@ -3023,7 +3026,7 @@ public void shouldPopulateResponseDebugExtensionAndWarningsIfDebugIsEnabled() { final List bidderResponses = singletonList(BidderResponse.of( "bidder1", BidderSeatBid.builder() - .bids(singletonList(BidderBid.of(bid, banner, null))) + .bids(singletonList(BidderBid.of(bid, banner, "seat", null))) .httpCalls(singletonList(ExtHttpCall.builder().status(200).build())) .build(), 100)); @@ -3087,7 +3090,7 @@ public void shouldPassIntegrationToCacheServiceAndBidEvents() { final Bid bid = Bid.builder().id("bidId1").impid(IMP_ID).price(BigDecimal.valueOf(5.67)).build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -3136,6 +3139,7 @@ public void shouldPopulateActivityInfrastructureTraceLogOnSpecifiedTraceLevel() givenSeatBid(BidderBid.of( Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(), banner, + "seat", "USD")), 100)); @@ -3174,7 +3178,7 @@ public void shouldPopulateBidResponseExtErrorIfImpExtIsInvalid() { final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -3194,7 +3198,7 @@ public void shouldThrowErrorIfBidIdAndCorrespondingImpIdNotEquals() { final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid("123").build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -3223,7 +3227,7 @@ public void shouldThrowExceptionWhenBidAdmIsParsedButImpNativeNotFound() throws final String bidder1 = "bidder1"; final List bidderResponses = List.of(BidderResponse.of(bidder1, - givenSeatBid(BidderBid.of(bid, xNative, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(givenImp("impId1")), @@ -3256,7 +3260,7 @@ public void shouldThrowExceptionWhenNativeRequestIsInvalid() throws JsonProcessi final String bidder1 = "bidder1"; final List bidderResponses = List.of(BidderResponse.of(bidder1, - givenSeatBid(BidderBid.of(bid, xNative, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final ObjectNode customObjectNode = mapper.createObjectNode(); customObjectNode.set("test-field", mapper @@ -3300,7 +3304,7 @@ public void shouldPopulateBidAdmIfResponseAssetsIsNull() throws JsonProcessingEx final String bidder1 = "bidder1"; final List bidderResponses = List.of(BidderResponse.of(bidder1, - givenSeatBid(BidderBid.of(bid, xNative, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(Imp.builder() @@ -3338,7 +3342,7 @@ public void shouldPopulateEventsContextForRequestIfEventsEnabledForRequest() { final Bid bid = Bid.builder().id("bidId1").impid(IMP_ID).price(BigDecimal.valueOf(5.67)).build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(bidRequestBuilder -> @@ -3376,7 +3380,7 @@ public void shouldNotPopulateBidExtTargetingWhenExtRequestTargetingPricegranular final Bid bidder1Bid1 = Bid.builder().id("bidder1Bid1").price(BigDecimal.valueOf(3.67)).impid("i1").build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bidder1Bid1, banner, null)), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bidder1Bid1, banner, "seat", null)), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -3411,7 +3415,7 @@ public void shouldNotPopulateBidExtTargetingWhenExtRequestTargetingSettingsIsFal final Bid bidder1Bid1 = Bid.builder().id("bidder1Bid1").price(BigDecimal.valueOf(3.67)).impid("i1").build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bidder1Bid1, banner, null)), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bidder1Bid1, banner, "seat", null)), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -3437,7 +3441,7 @@ public void shouldCopyRequestExtPrebidPassThroughToResponseExtPrebidPassThroughW // given final Bid bid = Bid.builder().id("bidder1Bid1").price(BigDecimal.valueOf(3.67)).impid("i1").build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, null)), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", null)), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -3468,7 +3472,7 @@ public void shouldCopyImpExtPrebidPassThroughToResponseBidExtPrebidPassThroughWh final Bid bid = Bid.builder().id("bidder1Bid1").price(BigDecimal.valueOf(3.67)).impid("i1").build(); final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, null)), 100)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "seat", null)), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -3501,7 +3505,7 @@ public void shouldAddExtPrebidFledgeIfAvailable() { final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .fledgeAuctionConfigs(List.of(fledgeAuctionConfig)) .build(), 100)); @@ -3542,7 +3546,7 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsIab() { final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .igi(singletonList(igi)) .build(), 100)); @@ -3584,7 +3588,7 @@ public void shouldAddExtPrebidFledgeIfAvailableAndExtRequestPrebidPaaFormatIsOri final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .igi(singletonList(igi)) .build(), 100)); @@ -3629,7 +3633,7 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsAbsentAndAcc final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .igi(singletonList(igi)) .build(), 100)); @@ -3675,7 +3679,7 @@ public void shouldAddExtPrebidFledgeIfAvailableAndRequestPaaFormatIsAbsentAndAcc final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .igi(singletonList(igi)) .build(), 100)); @@ -3724,7 +3728,7 @@ public void shouldDefaultToOriginalPaaFormat() { final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .igi(singletonList(igi)) .build(), 100)); @@ -3769,7 +3773,7 @@ public void shouldDropExtIgiIgbIfAvailableAndExtIgiImpIdIsAbsent() { final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .igi(singletonList(igi)) .build(), 100)); @@ -3826,7 +3830,7 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsImpIdIsAbsent() { final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .igi(singletonList(igi)) .build(), 100)); @@ -3879,7 +3883,7 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsConfigIsAbsent() { final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .igi(singletonList(igi)) .build(), 100)); @@ -3930,7 +3934,7 @@ public void shouldDropExtIgiIfAvailableAndExtIgiIgsAndExtIgiIgbAreAbsent() { final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() - .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .bids(List.of(BidderBid.of(bid, banner, "seat", "USD"))) .igi(singletonList(igi)) .build(), 100)); @@ -4024,7 +4028,7 @@ public void shouldPopulateExtPrebidSeatNonBidWhenReturnAllBidStatusFlagIsTrue() final List bidderResponses = singletonList( BidderResponse.of( "someBidder", - givenSeatBid(BidderBid.of(bid, banner, null)), + givenSeatBid(BidderBid.of(bid, banner, "seat", null)), 100)); final List auctionParticipations = toAuctionParticipant(bidderResponses); @@ -4060,7 +4064,7 @@ public void shouldNotPopulateExtPrebidSeatNonBidWhenReturnAllBidStatusFlagIsFals final List bidderResponses = singletonList( BidderResponse.of( "someBidder", - givenSeatBid(BidderBid.of(bid, banner, null)), + givenSeatBid(BidderBid.of(bid, banner, "seat", null)), 100)); final List auctionParticipations = toAuctionParticipant(bidderResponses); @@ -4105,7 +4109,7 @@ public void shouldPopulateBidExtWhenExtMediaTypePriceGranularityHasValidVideoExt final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -4151,7 +4155,7 @@ public void shouldPopulateBidExtWhenExtMediaTypePriceGranularityHasValidxNativeE final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest(identity(), extBuilder -> extBuilder.targeting(targeting), givenImp()), @@ -4194,7 +4198,7 @@ public void shouldThrowErrorIfExtMediaTypePriceGranularityCannotBeParsed() { final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -4219,7 +4223,7 @@ public void shouldPopulateTargetingKeywordsWithDefaultPrefixAndRelatedWarning() // given final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( identity(), @@ -4258,7 +4262,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromBid() { final Imp imp = Imp.builder().id("impId").exp(20).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, video, "USD")), + givenSeatBid(BidderBid.of(bid, video, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4327,7 +4331,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromImp() { final Imp imp = Imp.builder().id("impId").exp(20).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, video, "USD")), + givenSeatBid(BidderBid.of(bid, video, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4396,7 +4400,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromRequest() { final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, video, "USD")), + givenSeatBid(BidderBid.of(bid, video, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4465,7 +4469,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromAccountBanne final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4534,7 +4538,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromAccountVideo final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, video, "USD")), + givenSeatBid(BidderBid.of(bid, video, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4603,7 +4607,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromMediaTypeTtl final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4672,7 +4676,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromMediaTypeTtl final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, video, "USD")), + givenSeatBid(BidderBid.of(bid, video, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4741,7 +4745,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetDefaultTtlForBanner final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4810,7 +4814,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetDefaultTtlForVideoB final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, video, "USD")), + givenSeatBid(BidderBid.of(bid, video, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4879,7 +4883,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetDefaultTtlForAudioB final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, audio, "USD")), + givenSeatBid(BidderBid.of(bid, audio, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -4948,7 +4952,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetDefaultTtlForNative final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, xNative, "USD")), + givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -5017,7 +5021,7 @@ public void createShouldSendCacheRequestWithTtlFromMediaTypeWhenAccountIsEmpty() final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -5075,7 +5079,7 @@ public void createShouldSendCacheRequestWithNoTtlAndSetEmptyTtl() { final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -5133,7 +5137,7 @@ public void createShouldSendCacheRequestWithVideoBidWithTtlMaxOfTtlAndVideoTtl() final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, video, "USD")), + givenSeatBid(BidderBid.of(bid, video, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -5192,7 +5196,7 @@ public void createShouldSendCacheRequestWithBannerBidWithTtlMaxOfTtlAndVideoTtl( final Imp imp = Imp.builder().id("impId").exp(null).build(); final List bidderResponses = asList(BidderResponse.of( "bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), + givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -5351,6 +5355,7 @@ private static Map zipBidsWithCacheInfos(List bidInfos, private static BidInfo toBidInfo(Bid bid, Imp correspondingImp, String bidder, + String seat, BidType bidType, boolean isWinningBid) { @@ -5358,6 +5363,7 @@ private static BidInfo toBidInfo(Bid bid, .bid(bid) .correspondingImp(correspondingImp) .bidder(bidder) + .seat(seat) .bidType(bidType) .targetingInfo(TargetingInfo.builder() .bidderCode(bidder) diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index 2e8c9a5e2c1..8ea7f336e31 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -128,6 +128,7 @@ import org.prebid.server.proto.openrtb.ext.response.ExtAnalytics; import org.prebid.server.proto.openrtb.ext.response.ExtAnalyticsTags; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponse; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponsePrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidderError; @@ -1549,6 +1550,11 @@ public void shouldCallBidResponseCreatorWithExpectedParamsAndUpdateDebugErrors() .id("bidId3") .impid("impId3") .price(BigDecimal.valueOf(7.89)) + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder() + .adapterCode("bidder2") + .build()) + .build()))) .build(); final List auctionParticipations = contextArgumentCaptor.getValue().getAuctionParticipations(); @@ -1557,7 +1563,8 @@ public void shouldCallBidResponseCreatorWithExpectedParamsAndUpdateDebugErrors() .containsOnly( BidderResponse.of( "bidder2", - BidderSeatBid.of(singletonList(BidderBid.of(expectedThirdBid, banner, null))), + BidderSeatBid.of(singletonList( + BidderBid.of(expectedThirdBid, banner, "bidder2", null))), 0), BidderResponse.of("bidder1", BidderSeatBid.empty(), 0)); diff --git a/src/test/java/org/prebid/server/auction/adjustment/BidAdjustmentFactorResolverTest.java b/src/test/java/org/prebid/server/auction/adjustment/BidAdjustmentFactorResolverTest.java index 7ff8439a960..f9267899fd5 100644 --- a/src/test/java/org/prebid/server/auction/adjustment/BidAdjustmentFactorResolverTest.java +++ b/src/test/java/org/prebid/server/auction/adjustment/BidAdjustmentFactorResolverTest.java @@ -1,6 +1,5 @@ package org.prebid.server.auction.adjustment; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidAdjustmentFactors; import org.prebid.server.proto.openrtb.ext.request.ImpMediaType; @@ -13,25 +12,36 @@ public class BidAdjustmentFactorResolverTest { - private BidAdjustmentFactorResolver bidAdjustmentFactorResolver; - - @BeforeEach - public void setUp() { - bidAdjustmentFactorResolver = new BidAdjustmentFactorResolver(); - } + private final BidAdjustmentFactorResolver target = new BidAdjustmentFactorResolver(); @Test - public void resolveShouldReturnOneIfAdjustmentsByMediaTypeAndBidderAreAbsent() { + public void resolveShouldReturnOneIfAdjustmentsByMediaTypeAndBidderAreAbsentForBidderAndForSeat() { // when - final BigDecimal result = bidAdjustmentFactorResolver.resolve( + final BigDecimal result = target.resolve( ImpMediaType.video, ExtRequestBidAdjustmentFactors.builder().build(), - "bidder"); + "bidder1", + "bidder2"); // then assertThat(result).isEqualTo(BigDecimal.ONE); } + @Test + public void resolveShouldReturnSeatAdjustmentFactorOverBidderIfAdjustmentsByTypeAreAbsentIgnoringCase() { + // given + final ExtRequestBidAdjustmentFactors adjustmentFactors = + ExtRequestBidAdjustmentFactors.builder().build(); + adjustmentFactors.addFactor("BIDder", BigDecimal.valueOf(3.456)); + adjustmentFactors.addFactor("seat", BigDecimal.valueOf(4.456)); + + // when + final BigDecimal result = target.resolve(ImpMediaType.video, adjustmentFactors, "bidDER", "seAT"); + + // then + assertThat(result).isEqualTo(BigDecimal.valueOf(4.456)); + } + @Test public void resolveShouldReturnBidderAdjustmentFactorIfAdjustmentsByTypeAreAbsentIgnoringCase() { // given @@ -40,12 +50,62 @@ public void resolveShouldReturnBidderAdjustmentFactorIfAdjustmentsByTypeAreAbsen adjustmentFactors.addFactor("BIDder", BigDecimal.valueOf(3.456)); // when - final BigDecimal result = bidAdjustmentFactorResolver.resolve(ImpMediaType.video, adjustmentFactors, "bidDER"); + final BigDecimal result = target.resolve(ImpMediaType.video, adjustmentFactors, "bidDER", "seAT"); // then assertThat(result).isEqualTo(BigDecimal.valueOf(3.456)); } + @Test + public void resolveShouldReturnSeatAdjustmentByMediaTypeIfPresentIgnoringCase() { + // given + final EnumMap> adjustmentFactorsByMediaType = new EnumMap<>(Map.of( + ImpMediaType.video, Map.of( + "seat", BigDecimal.valueOf(0.234), + "BIDder", BigDecimal.valueOf(1.234)), + ImpMediaType.video_outstream, Map.of( + "bidder", BigDecimal.valueOf(2.345), + "SEAT", BigDecimal.valueOf(3.345)), + ImpMediaType.banner, Map.of("bidder", BigDecimal.valueOf(4.456)))); + + final ExtRequestBidAdjustmentFactors adjustmentFactors = + ExtRequestBidAdjustmentFactors.builder() + .mediatypes(adjustmentFactorsByMediaType) + .build(); + + adjustmentFactors.addFactor("BIDder", BigDecimal.valueOf(5.456)); + adjustmentFactors.addFactor("seat", BigDecimal.valueOf(6.456)); + + // when + final BigDecimal result = target.resolve(ImpMediaType.video, adjustmentFactors, "bidDER", "Seat"); + + // then + assertThat(result).isEqualTo(BigDecimal.valueOf(0.234)); + } + + @Test + public void resolveShouldReturnSeatAdjustmentFactorOverBidderByMediaTypeIfPresentIgnoringCase() { + // given + final EnumMap> adjustmentFactorsByMediaType = new EnumMap<>(Map.of( + ImpMediaType.video, Map.of("BIDder", BigDecimal.valueOf(1.234)), + ImpMediaType.video_outstream, Map.of("bidder", BigDecimal.valueOf(2.345)), + ImpMediaType.banner, Map.of("bidder", BigDecimal.valueOf(3.456)))); + + final ExtRequestBidAdjustmentFactors adjustmentFactors = + ExtRequestBidAdjustmentFactors.builder() + .mediatypes(adjustmentFactorsByMediaType) + .build(); + + adjustmentFactors.addFactor("BIDder", BigDecimal.valueOf(5.456)); + adjustmentFactors.addFactor("seat", BigDecimal.valueOf(6.456)); + + // when + final BigDecimal result = target.resolve(ImpMediaType.video, adjustmentFactors, "bidDER", "Seat"); + + // then + assertThat(result).isEqualTo(BigDecimal.valueOf(6.456)); + } + @Test public void resolveShouldReturnAdjustmentByMediaTypeIfPresentIgnoringCase() { // given @@ -59,8 +119,10 @@ public void resolveShouldReturnAdjustmentByMediaTypeIfPresentIgnoringCase() { .mediatypes(adjustmentFactorsByMediaType) .build(); + adjustmentFactors.addFactor("BIDder", BigDecimal.valueOf(5.456)); + // when - final BigDecimal result = bidAdjustmentFactorResolver.resolve(ImpMediaType.video, adjustmentFactors, "bidDER"); + final BigDecimal result = target.resolve(ImpMediaType.video, adjustmentFactors, "bidDER", "Seat"); // then assertThat(result).isEqualTo(BigDecimal.valueOf(1.234)); diff --git a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java index 2affb167eef..4bf637e7545 100644 --- a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java @@ -74,7 +74,7 @@ public class BidAdjustmentsProcessorTest extends VertxTest { public void before() { given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); target = new BidAdjustmentsProcessor( @@ -95,7 +95,8 @@ public void shouldReturnBidsWithUpdatedPriceCurrencyConversionAndAdjusted() { final AuctionParticipation auctionParticipation = givenAuctionParticipation(bidderResponse, bidRequest); final Price adjustedPrice = Price.of("EUR", BigDecimal.valueOf(5.0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())).willReturn(adjustedPrice); + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) + .willReturn(adjustedPrice); final BigDecimal expectedPrice = new BigDecimal("123.5"); given(currencyService.convertCurrency(any(), any(), eq("EUR"), eq("UAH"))).willReturn(expectedPrice); @@ -115,6 +116,7 @@ public void shouldReturnBidsWithUpdatedPriceCurrencyConversionAndAdjusted() { eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -130,7 +132,7 @@ public void shouldReturnSameBidPriceIfNoChangesAppliedToBidPrice() { given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocation -> invocation.getArgument(0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); // when @@ -181,7 +183,7 @@ public void shouldDropBidIfPrebidExceptionWasThrownDuringBidAdjustmentResolving( given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocation -> invocation.getArgument(0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) .willThrow(new PreBidException("Unable to convert bid currency CUR to desired ad server currency USD")); // when @@ -214,10 +216,11 @@ public void shouldUpdateBidPriceWithCurrencyConversionAndPriceAdjustmentFactorAn final AuctionParticipation auctionParticipation = givenAuctionParticipation(bidderResponse, bidRequest); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder", "seat")) .willReturn(BigDecimal.TEN); final Price adjustedPrice = Price.of("EUR", BigDecimal.valueOf(5.0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())).willReturn(adjustedPrice); + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) + .willReturn(adjustedPrice); final BigDecimal expectedPrice = new BigDecimal("123.5"); given(currencyService.convertCurrency(any(), any(), eq("EUR"), eq("UAH"))).willReturn(expectedPrice); @@ -238,6 +241,7 @@ public void shouldUpdateBidPriceWithCurrencyConversionAndPriceAdjustmentFactorAn eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -278,7 +282,7 @@ public void shouldUpdatePriceForOneBidAndDropAnotherIfPrebidExceptionHappensForS expectedBidExt.put("origbidcpm", new BigDecimal("2.0")); expectedBidExt.put("origbidcur", "CUR1"); final Bid expectedBid = Bid.builder().impid("impId1").price(updatedPrice).ext(expectedBidExt).build(); - final BidderBid expectedBidderBid = BidderBid.of(expectedBid, banner, "UAH"); + final BidderBid expectedBidderBid = BidderBid.of(expectedBid, banner, "seat", "UAH"); final BidderError expectedError = BidderError.generic("Unable to convert bid currency CUR2 to desired ad server currency USD"); @@ -326,7 +330,7 @@ public void shouldRespondWithOneBidAndErrorWhenBidResponseContainsOneUnsupported expectedBidExt.put("origbidcpm", new BigDecimal("2.0")); expectedBidExt.put("origbidcur", "USD"); final Bid expectedBid = Bid.builder().impid("impId1").price(updatedPrice).ext(expectedBidExt).build(); - final BidderBid expectedBidderBid = BidderBid.of(expectedBid, banner, "CUR"); + final BidderBid expectedBidderBid = BidderBid.of(expectedBid, banner, "seat", "CUR"); assertThat(result.getBidderResponse().getSeatBid().getBids()).containsOnly(expectedBidderBid); final BidderError expectedError = BidderError.generic( @@ -376,7 +380,7 @@ public void shouldUpdateBidPriceWithCurrencyConversionForMultipleBid() { .extracting(Bid::getPrice) .containsOnly(bidder3Price, updatedPrice, updatedPrice); - verify(bidAdjustmentsResolver, times(3)).resolve(any(), any(), any(), any(), any(), any()); + verify(bidAdjustmentsResolver, times(3)).resolve(any(), any(), any(), any(), any(), any(), any()); } @Test @@ -387,7 +391,7 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentFactorPresent() { final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder().build(); givenAdjustments.addFactor("bidder", BigDecimal.valueOf(2.468)); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder", "seat")) .willReturn(BigDecimal.valueOf(2.468)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), @@ -415,6 +419,7 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentFactorPresent() { eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -438,7 +443,7 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP .mediatypes(new EnumMap<>(singletonMap(ImpMediaType.video, singletonMap("bidder", BigDecimal.valueOf(3.456))))) .build(); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video, givenAdjustments, "bidder")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video, givenAdjustments, "bidder", "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), impBuilder -> @@ -467,6 +472,7 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP eq(givenBidAdjustments()), eq(ImpMediaType.video_instream), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -490,7 +496,7 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP .mediatypes(new EnumMap<>(singletonMap(ImpMediaType.video, singletonMap("bidder", BigDecimal.valueOf(3.456))))) .build(); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video, givenAdjustments, "bidder")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video, givenAdjustments, "bidder", "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), impBuilder -> @@ -519,6 +525,7 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP eq(givenBidAdjustments()), eq(ImpMediaType.video_instream), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -542,7 +549,7 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoOutstreamMediaTypeIfVideo .mediatypes(new EnumMap<>(singletonMap(ImpMediaType.video, singletonMap("bidder", BigDecimal.valueOf(3.456))))) .build(); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video_outstream, givenAdjustments, "bidder")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video_outstream, givenAdjustments, "bidder", "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), impBuilder -> @@ -570,6 +577,7 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoOutstreamMediaTypeIfVideo eq(givenBidAdjustments()), eq(ImpMediaType.video_outstream), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -614,13 +622,14 @@ public void shouldReturnBidAdjustmentMediaTypeVideoOutstreamIfImpIdNotEqualBidIm .extracting(Bid::getPrice) .containsExactly(BigDecimal.valueOf(2)); - verify(bidAdjustmentFactorResolver).resolve(ImpMediaType.video_outstream, givenAdjustments, "bidder"); + verify(bidAdjustmentFactorResolver).resolve(ImpMediaType.video_outstream, givenAdjustments, "bidder", "seat"); verify(bidAdjustmentsResolver).resolve( eq(Price.of("USD", BigDecimal.valueOf(2))), eq(bidRequest), eq(givenBidAdjustments()), eq(ImpMediaType.video_outstream), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -671,6 +680,7 @@ public void shouldReturnBidAdjustmentMediaTypeVideoOutStreamIfImpIdEqualBidImpId eq(givenBidAdjustments()), eq(ImpMediaType.video_outstream), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -691,7 +701,7 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentMediaFactorPresent() .mediatypes(new EnumMap<>(singletonMap(ImpMediaType.banner, singletonMap("bidder", BigDecimal.valueOf(3.456))))) .build(); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder", "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), @@ -714,7 +724,7 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentMediaFactorPresent() .containsExactly(BigDecimal.valueOf(6.912), BigDecimal.valueOf(1), BigDecimal.valueOf(1)); verify(bidAdjustmentsResolver, times(3)) - .resolve(any(), any(), any(), any(), any(), any()); + .resolve(any(), any(), any(), any(), any(), any(), any()); } @Test @@ -738,7 +748,7 @@ public void shouldAdjustPriceWithPriorityForMediaTypeAdjustment() { singletonMap("bidder", BigDecimal.valueOf(3.456))))) .build(); givenAdjustments.addFactor("bidder", BigDecimal.valueOf(2.468)); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder", "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), @@ -766,6 +776,7 @@ public void shouldAdjustPriceWithPriorityForMediaTypeAdjustment() { eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -814,6 +825,7 @@ public void shouldReturnBidsWithoutAdjustingPricesWhenAdjustmentFactorNotPresent eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), + eq("seat"), eq("dealId")); } @@ -834,11 +846,11 @@ private static Imp givenImp(T ext, UnaryOperator impBuilderC } private static BidderBid givenBidderBid(Bid bid, String currency) { - return BidderBid.of(bid, banner, currency); + return BidderBid.of(bid, banner, "seat", currency); } private static BidderBid givenBidderBid(Bid bid, String currency, BidType type) { - return BidderBid.of(bid, type, currency); + return BidderBid.of(bid, type, "seat", currency); } private static Map doubleMap(K key1, V value1, K key2, V value2) { @@ -856,7 +868,7 @@ private BidderResponse givenBidderResponse(Bid bid) { return BidderResponse.of( "bidder", BidderSeatBid.builder() - .bids(singletonList(givenBidderBid(bid, "USD"))) + .bids(singletonList(givenBidderBid(bid, "USD", banner))) .build(), 1); } diff --git a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java index 97ca68e939e..82594c506b9 100644 --- a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java @@ -59,6 +59,7 @@ public void resolveShouldPickAndApplyRulesBySpecificMediaType() { givenBidAdjustments, ImpMediaType.banner, "bidderName", + "seat", "dealId"); // then @@ -82,6 +83,7 @@ public void resolveShouldPickAndApplyRulesByWildcardMediaType() { givenBidAdjustments, ImpMediaType.video_outstream, "bidderName", + "seat", "dealId"); // then @@ -90,10 +92,10 @@ public void resolveShouldPickAndApplyRulesByWildcardMediaType() { } @Test - public void resolveShouldPickAndApplyRulesBySpecificBidder() { + public void resolveShouldPickAndApplyRulesBySpecificSeat() { // given final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( - "*|bidderName|*", List.of(givenMultiplier("15")), + "*|seat|*", List.of(givenMultiplier("15")), "*|*|*", List.of(givenMultiplier("25")))); // when @@ -103,6 +105,7 @@ public void resolveShouldPickAndApplyRulesBySpecificBidder() { givenBidAdjustments, ImpMediaType.banner, "bidderName", + "seat", "dealId"); // then @@ -111,10 +114,10 @@ public void resolveShouldPickAndApplyRulesBySpecificBidder() { } @Test - public void resolveShouldPickAndApplyRulesByWildcardBidder() { + public void resolveShouldPickAndApplyRulesByWildcardSeat() { // given final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( - "*|bidderName|*", List.of(givenStatic("15", "EUR"), givenMultiplier("15")), + "*|seat|*", List.of(givenStatic("15", "EUR"), givenMultiplier("15")), "*|*|*", List.of(givenStatic("25", "UAH"), givenMultiplier("25")))); // when @@ -124,6 +127,51 @@ public void resolveShouldPickAndApplyRulesByWildcardBidder() { givenBidAdjustments, ImpMediaType.banner, "anotherBidderName", + "anotherSeat", + "dealId"); + + // then + assertThat(actual).isEqualTo(Price.of("UAH", new BigDecimal("625"))); + verifyNoInteractions(currencyService); + } + + @Test + public void resolveShouldPickAndApplyRulesByWildcardSeatOverSpecificBidder() { + // given + final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( + "*|bidderName|*", List.of(givenMultiplier("15")), + "*|*|*", List.of(givenMultiplier("25")))); + + // when + final Price actual = target.resolve( + Price.of("USD", BigDecimal.ONE), + BidRequest.builder().build(), + givenBidAdjustments, + ImpMediaType.banner, + "bidderName", + "seat", + "dealId"); + + // then + assertThat(actual).isEqualTo(Price.of("USD", new BigDecimal("25"))); + verifyNoInteractions(currencyService); + } + + @Test + public void resolveShouldPickAndApplyRulesBySpecificSeatOverSpecificBidder() { + // given + final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( + "*|bidderName|*", List.of(givenStatic("15", "EUR"), givenMultiplier("15")), + "*|seat|*", List.of(givenStatic("25", "UAH"), givenMultiplier("25")))); + + // when + final Price actual = target.resolve( + Price.of("USD", BigDecimal.ONE), + BidRequest.builder().build(), + givenBidAdjustments, + ImpMediaType.banner, + "bidderName", + "seat", "dealId"); // then @@ -131,6 +179,28 @@ public void resolveShouldPickAndApplyRulesByWildcardBidder() { verifyNoInteractions(currencyService); } + @Test + public void resolveShouldPickAndApplyRulesBySpecificBidderWhenSeatRuleIsNotMatched() { + // given + final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( + "*|bidderName|*", List.of(givenStatic("15", "EUR"), givenMultiplier("15")), + "*|anotherBidder|*", List.of(givenStatic("25", "UAH"), givenMultiplier("25")))); + + // when + final Price actual = target.resolve( + Price.of("USD", BigDecimal.ONE), + BidRequest.builder().build(), + givenBidAdjustments, + ImpMediaType.banner, + "bidderName", + "seat", + "dealId"); + + // then + assertThat(actual).isEqualTo(Price.of("EUR", new BigDecimal("225"))); + verifyNoInteractions(currencyService); + } + @Test public void resolveShouldPickAndApplyRulesBySpecificDealId() { // given @@ -146,6 +216,7 @@ public void resolveShouldPickAndApplyRulesBySpecificDealId() { givenBidAdjustments, ImpMediaType.banner, "bidderName", + "seat", "dealId"); // then @@ -168,6 +239,7 @@ public void resolveShouldPickAndApplyRulesByWildcardDealId() { givenBidAdjustments, ImpMediaType.banner, "bidderName", + "seat", "anotherDealId"); // then @@ -190,6 +262,7 @@ public void resolveShouldPickAndApplyRulesByWildcardDealIdWhenDealIdIsNull() { givenBidAdjustments, ImpMediaType.banner, "bidderName", + "seat", null); // then @@ -211,6 +284,7 @@ public void resolveShouldReturnEmptyListWhenNoMatchFound() { givenBidAdjustments, ImpMediaType.banner, "bidderName", + "seat", null); // then diff --git a/src/test/java/org/prebid/server/bidder/amx/AmxBidderTest.java b/src/test/java/org/prebid/server/bidder/amx/AmxBidderTest.java index bf5d788808f..d7e7c053209 100644 --- a/src/test/java/org/prebid/server/bidder/amx/AmxBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/amx/AmxBidderTest.java @@ -203,6 +203,26 @@ public void makeBidsShouldReturnBannerBidIfBannerIsBidExtNotPresent() throws Jso .containsExactly(BidderBid.of(Bid.builder().build(), banner, "USD")); } + @Test + public void makeBidsShouldReturnBannerBidWithSeatSetWhenBidderCodeIsPresentInBidExt() + throws JsonProcessingException { + + // given + final ObjectNode bidExt = mapper.createObjectNode(); + bidExt.put("bc", "seat"); + final BidderCall httpCall = givenHttpCall(BidRequest.builder().build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.ext(bidExt)))); + + // when + final Result> result = target.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().ext(bidExt).build(), banner, "seat", "USD")); + } + @Test public void makeBidsShouldReturnVideoBidIfStartDelayIsPresentInBidExt() throws JsonProcessingException { // given diff --git a/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java b/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java index ae22bb5a300..58f5b4d5a02 100644 --- a/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java @@ -1138,7 +1138,7 @@ public void makeBidderResponseShouldFillExtBidPrebidVideoDurationIfDurationIsNot mapper.writeValueAsString( givenBidResponse(bidBuilder -> bidBuilder.impid("123") .ext(mapper.valueToTree( - PubmaticBidExt.of(null, VideoCreativeInfo.of(1), null)))))); + PubmaticBidExt.of(null, VideoCreativeInfo.of(1), null, null)))))); // when final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); @@ -1161,7 +1161,7 @@ public void makeBidderResponseShouldNotFillExtBidPrebidVideoDurationIfDurationIs mapper.writeValueAsString( givenBidResponse(bidBuilder -> bidBuilder.impid("123") .ext(mapper.valueToTree( - PubmaticBidExt.of(null, VideoCreativeInfo.of(null), null)))))); + PubmaticBidExt.of(null, VideoCreativeInfo.of(null), null, null)))))); // when final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); @@ -1182,7 +1182,7 @@ public void makeBidderResponseShouldNotFillExtBidPrebidVideoDurationIfVideoIsNul mapper.writeValueAsString( givenBidResponse(bidBuilder -> bidBuilder.impid("123") .ext(mapper.valueToTree( - PubmaticBidExt.of(null, null, null)))))); + PubmaticBidExt.of(null, null, null, null)))))); // when final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); @@ -1200,7 +1200,7 @@ public void makeBidderResponseShouldFillDealPriorityData() throws JsonProcessing mapper.writeValueAsString( givenBidResponse(bidBuilder -> bidBuilder.impid("123") .ext(mapper.valueToTree( - PubmaticBidExt.of(null, null, 12)))))); + PubmaticBidExt.of(null, null, 12, null)))))); // when final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); @@ -1212,6 +1212,25 @@ public void makeBidderResponseShouldFillDealPriorityData() throws JsonProcessing .containsExactly(12); } + @Test + public void makeBidderResponseShouldFillSeat() throws JsonProcessingException { + // given + final BidderCall httpCall = givenHttpCall( + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123") + .ext(mapper.valueToTree( + PubmaticBidExt.of(null, null, 12, "marketplace")))))); + + // when + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getBids()) + .extracting(BidderBid::getSeat) + .containsExactly("marketplace"); + } + @Test public void makeBidderResponseShouldParseNativeAdmData() throws JsonProcessingException { // given @@ -1224,7 +1243,7 @@ public void makeBidderResponseShouldParseNativeAdmData() throws JsonProcessingEx givenBidResponse(bidBuilder -> bidBuilder.impid("123") .adm(admNode.toString()) .ext(mapper.valueToTree( - PubmaticBidExt.of(2, null, 12)))))); + PubmaticBidExt.of(2, null, 12, null)))))); // when final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); diff --git a/src/test/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidderTest.java b/src/test/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidderTest.java index dbcc555489a..9bd1656433e 100644 --- a/src/test/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidderTest.java @@ -4,17 +4,14 @@ import com.iab.openrtb.request.Audio; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Site; import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; -import com.iab.openrtb.response.BidResponse; -import com.iab.openrtb.response.SeatBid; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.VertxTest; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; @@ -22,484 +19,484 @@ import org.prebid.server.bidder.model.HttpRequest; import org.prebid.server.bidder.model.HttpResponse; import org.prebid.server.bidder.model.Result; -import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.exception.PreBidException; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalImp; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpMediaType; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpMediaTypes; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpZone; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalRequest; +import org.prebid.server.bidder.resetdigital.request.ResetDigitalSite; +import org.prebid.server.bidder.resetdigital.response.ResetDigitalBid; +import org.prebid.server.bidder.resetdigital.response.ResetDigitalResponse; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.resetdigital.ExtImpResetDigital; import java.math.BigDecimal; import java.util.List; +import java.util.Set; import java.util.function.UnaryOperator; +import java.util.stream.Stream; -import static java.util.Collections.singletonList; import static java.util.function.UnaryOperator.identity; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.AssertionsForClassTypes.tuple; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; import static org.prebid.server.proto.openrtb.ext.response.BidType.audio; import static org.prebid.server.proto.openrtb.ext.response.BidType.banner; import static org.prebid.server.proto.openrtb.ext.response.BidType.video; +import static org.prebid.server.util.HttpUtil.ACCEPT_HEADER; +import static org.prebid.server.util.HttpUtil.ACCEPT_LANGUAGE_HEADER; +import static org.prebid.server.util.HttpUtil.APPLICATION_JSON_CONTENT_TYPE; +import static org.prebid.server.util.HttpUtil.CONTENT_TYPE_HEADER; +import static org.prebid.server.util.HttpUtil.REFERER_HEADER; +import static org.prebid.server.util.HttpUtil.USER_AGENT_HEADER; +import static org.prebid.server.util.HttpUtil.X_FORWARDED_FOR_HEADER; +import static org.prebid.server.util.HttpUtil.X_REAL_IP_HEADER; +import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE; -@ExtendWith(MockitoExtension.class) public class ResetDigitalBidderTest extends VertxTest { public static final String ENDPOINT_URL = "https://test.endpoint.com"; - @Mock - private CurrencyConversionService currencyConversionService; - private ResetDigitalBidder target; @BeforeEach public void setUp() { - target = new ResetDigitalBidder(ENDPOINT_URL, currencyConversionService, jacksonMapper); + target = new ResetDigitalBidder(ENDPOINT_URL, jacksonMapper); } @Test public void creationShouldFailOnInvalidEndpointUrl() { assertThatIllegalArgumentException().isThrownBy(() -> - new ResetDigitalBidder("invalid_url", currencyConversionService, jacksonMapper)); + new ResetDigitalBidder("invalid_url", jacksonMapper)); } @Test - public void makeHttpRequestShouldReturnEmptyResponseIfAbsentAnyTypeInImp() { + public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(impBuilder -> impBuilder.banner(null)))) - .build(); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).hasSize(0); - assertThat(result.getValue()).hasSize(0); - } - - @Test - public void makeHttpRequestShouldReturnEmptyResponseIfxNativeImpTypePresent() { - // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(impBuilder -> impBuilder.banner(null) - .xNative(Native.builder().build())))) - .build(); + final BidRequest bidRequest = givenBidRequest( + imp -> imp.ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode())))); // when - final Result>> result = target.makeHttpRequests(bidRequest); + final Result>> result = target.makeHttpRequests(bidRequest); // then - assertThat(result.getErrors()).hasSize(0); - assertThat(result.getValue()).hasSize(0); + assertThat(result.getValue()).isEmpty(); + assertThat(result.getErrors()).hasSize(1).allSatisfy(bidderError -> { + assertThat(bidderError.getType()).isEqualTo(BidderError.Type.bad_input); + assertThat(bidderError.getMessage()).startsWith("Cannot deserialize value"); + }); } @Test - public void makeHttpRequestShouldReturnSeparateResponseWithBannerAndVideoAndAudioImp() { + public void makeHttpRequestsShouldMakeOneRequestPerImp() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(impBuilder -> impBuilder - .audio(Audio.builder().build()) - .video(Video.builder().build())))) - .build(); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); + final BidRequest bidRequest = givenBidRequest( + imp -> imp.id("givenImp1"), + imp -> imp.id("givenImp2"), + imp -> imp.id("givenImp3")); - // then - assertThat(result.getErrors()).hasSize(0); - assertThat(result.getValue()).hasSize(3); - assertThat(result.getValue().get(0)) - .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getImp) - .extracting(a -> a.getFirst()) - .extracting(Imp::getBanner) - .isNotNull(); + //when + final Result>> result = target.makeHttpRequests(bidRequest); - assertThat(result.getValue().get(1)) + //then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(3) .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getImp) - .extracting(a -> a.getFirst()) - .extracting(Imp::getVideo) - .isNotNull(); + .flatExtracting(ResetDigitalRequest::getImps) + .extracting(ResetDigitalImp::getImpId) + .containsExactlyInAnyOrder("givenImp1", "givenImp2", "givenImp3"); - assertThat(result.getValue().get(2)) - .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getImp) - .extracting(a -> a.getFirst()) - .extracting(Imp::getAudio) - .isNotNull(); + assertThat(result.getValue()).hasSize(3) + .extracting(HttpRequest::getImpIds) + .containsExactlyInAnyOrder(Set.of("givenImp1"), Set.of("givenImp2"), Set.of("givenImp3")); } @Test - public void makeHttpRequestShouldReturnSeparateResponseWithBannerAndVideoImp() { + public void makeHttpRequestsShouldHaveCorrectUri() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(impBuilder -> impBuilder - .video(Video.builder().build())))) - .build(); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); + final BidRequest bidRequest = givenBidRequest(imp -> imp.id("givenImp")); - // then - assertThat(result.getErrors()).hasSize(0); - assertThat(result.getValue()).hasSize(2); - assertThat(result.getValue().get(0)) - .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getImp) - .extracting(a -> a.getFirst()) - .extracting(Imp::getBanner) - .isNotNull(); + //when + final Result>> result = target.makeHttpRequests(bidRequest); - assertThat(result.getValue().get(1)) - .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getImp) - .extracting(a -> a.getFirst()) - .extracting(Imp::getVideo) - .isNotNull(); + //then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getUri) + .containsExactlyInAnyOrder(ENDPOINT_URL); } @Test - public void makeHttpRequestShouldReturnSeparateResponseWithBannerAndAudioImp() { + public void makeHttpRequestsShouldReturnExpectedHeaders() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(impBuilder -> impBuilder - .audio(Audio.builder().build())))) + final BidRequest bidRequest = givenBidRequest(identity()).toBuilder() + .device(Device.builder().ip("ip").ua("ua").language("lang").build()) + .site(Site.builder().page("page").build()) .build(); // when - final Result>> result = target.makeHttpRequests(bidRequest); + final Result>> result = target.makeHttpRequests(bidRequest); // then - assertThat(result.getErrors()).hasSize(0); - assertThat(result.getValue()).hasSize(2); - assertThat(result.getValue().get(0)) - .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getImp) - .extracting(a -> a.getFirst()) - .extracting(Imp::getBanner) - .isNotNull(); - - assertThat(result.getValue().get(1)) - .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getImp) - .extracting(a -> a.getFirst()) - .extracting(Imp::getAudio) - .isNotNull(); + assertThat(result.getValue()).hasSize(1).first() + .extracting(HttpRequest::getHeaders) + .satisfies(headers -> { + assertThat(headers.get(CONTENT_TYPE_HEADER)).isEqualTo(APPLICATION_JSON_CONTENT_TYPE); + assertThat(headers.get(ACCEPT_HEADER)).isEqualTo(APPLICATION_JSON_VALUE); + assertThat(headers.get(USER_AGENT_HEADER)).isEqualTo("ua"); + assertThat(headers.get(ACCEPT_LANGUAGE_HEADER)).isEqualTo("lang"); + assertThat(headers.get(X_FORWARDED_FOR_HEADER)).isEqualTo("ip"); + assertThat(headers.get(X_REAL_IP_HEADER)).isEqualTo("ip"); + assertThat(headers.get(REFERER_HEADER)).isEqualTo("page"); + }); + assertThat(result.getErrors()).isEmpty(); } @Test - public void makeHttpRequestShouldReturnSeparateResponseWithVideoAndAudioImp() { + public void makeHttpRequestsShouldReturnExpectedHeadersWhenDeviceAndSiteAreNotPresent() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(impBuilder -> impBuilder - .banner(null) - .video(Video.builder().build()) - .audio(Audio.builder().build())))) - .build(); + final BidRequest bidRequest = givenBidRequest(identity()); // when - final Result>> result = target.makeHttpRequests(bidRequest); + final Result>> result = target.makeHttpRequests(bidRequest); // then - assertThat(result.getErrors()).hasSize(0); - assertThat(result.getValue()).hasSize(2); - assertThat(result.getValue().get(0)) - .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getImp) - .extracting(a -> a.getFirst()) - .extracting(Imp::getVideo) - .isNotNull(); - - assertThat(result.getValue().get(1)) - .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getImp) - .extracting(a -> a.getFirst()) - .extracting(Imp::getAudio) - .isNotNull(); + assertThat(result.getValue()).hasSize(1).first() + .extracting(HttpRequest::getHeaders) + .satisfies(headers -> { + assertThat(headers.get(CONTENT_TYPE_HEADER)).isEqualTo(APPLICATION_JSON_CONTENT_TYPE); + assertThat(headers.get(ACCEPT_HEADER)).isEqualTo(APPLICATION_JSON_VALUE); + assertThat(headers.get(USER_AGENT_HEADER)).isNull(); + assertThat(headers.get(ACCEPT_LANGUAGE_HEADER)).isNull(); + assertThat(headers.get(X_FORWARDED_FOR_HEADER)).isNull(); + assertThat(headers.get(X_REAL_IP_HEADER)).isNull(); + assertThat(headers.get(REFERER_HEADER)).isNull(); + }); + assertThat(result.getErrors()).isEmpty(); } @Test - public void makeHttpRequestShouldReturnResponseOnlyWithBannerImp() { + public void makeHttpRequestsShouldReturnBannerRequestFromBannerImp() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(identity()))) + final BidRequest bidRequest = givenBidRequest(imp -> imp + .id("impId") + .banner(Banner.builder().w(1).h(2).build())) + .toBuilder() + .id("requestId") .build(); - // when - final Result>> result = target.makeHttpRequests(bidRequest); + //when + final Result>> result = target.makeHttpRequests(bidRequest); - // then - assertThat(result.getErrors()).hasSize(0); - assertThat(result.getValue()) + //then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) .extracting(HttpRequest::getPayload) - .flatExtracting(BidRequest::getImp) - .allSatisfy(imp -> { - assertThat(imp.getBanner()).isNotNull(); - assertThat(imp.getVideo()).isNull(); - assertThat(imp.getAudio()).isNull(); - }); + .flatExtracting(ResetDigitalRequest::getImps) + .containsExactlyInAnyOrder(ResetDigitalImp.builder() + .impId("impId") + .bidId("requestId") + .zoneId(ResetDigitalImpZone.of("placementId")) + .mediaTypes(ResetDigitalImpMediaTypes.banner(ResetDigitalImpMediaType.builder() + .sizes(List.of(List.of(1, 2))) + .build())) + .build()); } @Test - public void makeHttpRequestShouldReturnResponseOnlyWithVideoImp() { + public void makeHttpRequestsShouldReturnVideoRequestFromVideoImp() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(impBuilder -> impBuilder.banner(null) - .video(Video.builder().build())))) + final BidRequest bidRequest = givenBidRequest(imp -> imp + .id("impId") + .banner(null) + .video(Video.builder().w(1).h(2).mimes(List.of("mime1", "mime2")).build())) + .toBuilder() + .id("requestId") .build(); - // when - final Result>> result = target.makeHttpRequests(bidRequest); + //when + final Result>> result = target.makeHttpRequests(bidRequest); - // then - assertThat(result.getErrors()).hasSize(0); - assertThat(result.getValue()) + //then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) .extracting(HttpRequest::getPayload) - .flatExtracting(BidRequest::getImp) - .allSatisfy(imp -> { - assertThat(imp.getBanner()).isNull(); - assertThat(imp.getVideo()).isNotNull(); - assertThat(imp.getAudio()).isNull(); - }); + .flatExtracting(ResetDigitalRequest::getImps) + .containsExactlyInAnyOrder(ResetDigitalImp.builder() + .impId("impId") + .bidId("requestId") + .zoneId(ResetDigitalImpZone.of("placementId")) + .mediaTypes(ResetDigitalImpMediaTypes.video(ResetDigitalImpMediaType.builder() + .sizes(List.of(List.of(1, 2))) + .mimes(List.of("mime1", "mime2")) + .build())) + .build()); } @Test - public void makeHttpRequestShouldReturnResponseOnlyWithAudioImp() { + public void makeHttpRequestsShouldReturnAudioRequestFromAudioImp() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(givenImp(impBuilder -> impBuilder.banner(null) - .audio(Audio.builder().build())))) + final BidRequest bidRequest = givenBidRequest(imp -> imp + .id("impId") + .banner(null) + .audio(Audio.builder().mimes(List.of("mime1", "mime2")).build())) + .toBuilder() + .id("requestId") .build(); - // when - final Result>> result = target.makeHttpRequests(bidRequest); + //when + final Result>> result = target.makeHttpRequests(bidRequest); - // then - assertThat(result.getErrors()).hasSize(0); - assertThat(result.getValue()) + //then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) .extracting(HttpRequest::getPayload) - .flatExtracting(BidRequest::getImp) - .allSatisfy(imp -> { - assertThat(imp.getBanner()).isNull(); - assertThat(imp.getVideo()).isNull(); - assertThat(imp.getAudio()).isNotNull(); - }); + .flatExtracting(ResetDigitalRequest::getImps) + .containsExactlyInAnyOrder(ResetDigitalImp.builder() + .impId("impId") + .bidId("requestId") + .zoneId(ResetDigitalImpZone.of("placementId")) + .mediaTypes(ResetDigitalImpMediaTypes.audio(ResetDigitalImpMediaType.builder() + .mimes(List.of("mime1", "mime2")) + .build())) + .build()); } @Test - public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { + public void makeHttpRequestsShouldReturnFailWhenImpIsNative() { // given - final BidderCall httpCall = givenHttpCall(null, "invalid"); + final BidRequest bidRequest = givenBidRequest(imp -> imp + .id("impId") + .banner(null) + .xNative(Native.builder().build())) + .toBuilder() + .id("requestId") + .build(); - // when - final Result> result = target.makeBids(httpCall, null); + //when + final Result>> result = target.makeHttpRequests(bidRequest); - // then - assertThat(result.getErrors()).hasSize(1) - .allSatisfy(error -> { - assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); - assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token"); - }); + //then assertThat(result.getValue()).isEmpty(); + assertThat(result.getErrors()).hasSize(1).allSatisfy(bidderError -> { + assertThat(bidderError.getType()).isEqualTo(BidderError.Type.bad_input); + assertThat(bidderError.getMessage()).isEqualTo("Banner, video or audio must be present in the imp impId"); + }); } @Test - public void makeHttpRequestsShouldConvertCurrencyIfRequestCurrencyDoesNotMatchBidderCurrency() { + public void makeHttpRequestsShouldReturnCorrectSite() { // given - given(currencyConversionService.convertCurrency(any(), any(), anyString(), anyString())) - .willReturn(BigDecimal.TEN); - - final BidRequest bidRequest = givenBidRequest( - impBuilder -> impBuilder.bidfloor(BigDecimal.ONE).bidfloorcur("EUR")); + final BidRequest bidRequest = givenBidRequest(identity()) + .toBuilder() + .site(Site.builder().domain("domain").page("page").build()) + .build(); - // when - final Result>> result = target.makeHttpRequests(bidRequest); + //when + final Result>> result = target.makeHttpRequests(bidRequest); - // then + //then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) + assertThat(result.getValue()).hasSize(1) .extracting(HttpRequest::getPayload) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getBidfloor, Imp::getBidfloorcur) - .containsOnly(tuple(BigDecimal.TEN, "USD")); + .flatExtracting(ResetDigitalRequest::getSite) + .containsExactlyInAnyOrder(ResetDigitalSite.builder() + .referrer("page") + .domain("domain") + .build()); } @Test - public void makeHttpRequestsShouldReturnErrorMessageOnFailedCurrencyConversion() { + public void makeBidsShouldReturnErrorWhenResponseCanNotBeParsed() { // given - given(currencyConversionService.convertCurrency(any(), any(), anyString(), anyString())) - .willThrow(PreBidException.class); - - final BidRequest bidRequest = givenBidRequest( - impCustomizer -> impCustomizer.bidfloor(BigDecimal.ONE).bidfloorcur("EUR")); + final BidderCall httpCall = givenHttpCall("invalid"); // when - final Result>> result = target.makeHttpRequests(bidRequest); + final Result> actual = target.makeBids(httpCall, null); // then - assertThat(result.getErrors()).allSatisfy(bidderError -> { - assertThat(bidderError.getType()) - .isEqualTo(BidderError.Type.bad_input); - assertThat(bidderError.getMessage()) - .isEqualTo("Unable to convert provided bid floor currency from EUR to USD for imp `123`"); - }); + assertThat(actual.getValue()).isEmpty(); + assertThat(actual.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token 'invalid':"); + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); + }); } @Test - public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + public void makeBidsShouldReturnEmptyBidsWhenResponseDoesNotHaveBids() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString(null)); + final BidderCall httpCall = givenHttpCall(givenBidResponse()); // when - final Result> result = target.makeBids(httpCall, null); + final Result> actual = target.makeBids(httpCall, null); // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).isEmpty(); + assertThat(actual.getValue()).isEmpty(); + assertThat(actual.getErrors()) + .containsOnly(BidderError.badServerResponse("expected exactly one bid in the response, but got 0")); } @Test - public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + public void makeBidsShouldReturnEmptyBidsWhenResponseHasMoreThanOneBid() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall(null, - mapper.writeValueAsString(BidResponse.builder().build())); + final BidderCall httpCall = givenHttpCall(givenBidResponse(identity(), identity())); // when - final Result> result = target.makeBids(httpCall, null); + final Result> actual = target.makeBids(httpCall, null); // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).isEmpty(); + assertThat(actual.getValue()).isEmpty(); + assertThat(actual.getErrors()) + .containsOnly(BidderError.badServerResponse("expected exactly one bid in the response, but got 2")); } @Test - public void makeBidsShouldReturnBannerBidIfBannerIsPresentInRequestImp() throws JsonProcessingException { - // given - final BidderCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").banner(Banner.builder().build()).build())) - .build(), - mapper.writeValueAsString( - givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + public void makeBidsShouldReturnEmptyBidsWhenResponseDoesNotHaveBidThatMatchesAnyImp() + throws JsonProcessingException { - // when - final Result> result = target.makeBids(httpCall, null); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) - .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); - } - - @Test - public void makeBidsShouldReturnVideoBidIfVideoIsPresentInRequestImp() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").video(Video.builder().build()).build())) - .build(), - mapper.writeValueAsString( - givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + final BidderCall httpCall = givenHttpCall(givenBidResponse(bid -> bid.impId("impId1"))); // when - final Result> result = target.makeBids(httpCall, null); + final Result> actual = target.makeBids(httpCall, givenBidRequest(imp -> imp.id("impId2"))); // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) - .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), video, "USD")); + assertThat(actual.getValue()).isEmpty(); + assertThat(actual.getErrors()) + .containsOnly(BidderError.badServerResponse("no matching impression found for ImpID impId1")); } @Test - public void makeBidsShouldReturnAudioBidIfAudioIsPresentInRequestImp() throws JsonProcessingException { + public void makeBidsShouldReturnBannerBidSuccessfully() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").audio(Audio.builder().build()).build())) - .build(), - mapper.writeValueAsString( - givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + final BidderCall httpCall = givenHttpCall(givenBidResponse(bid -> bid + .cpm(BigDecimal.TEN) + .cid("cid") + .html("html") + .crid("crid") + .seat("seat") + .impId("impId") + .bidId("bidId") + .w("1") + .h("2"))); // when - final Result> result = target.makeBids(httpCall, null); + final Result> result = target.makeBids( + httpCall, + givenBidRequest(imp -> imp.id("impId").banner(Banner.builder().build()))); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) - .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), audio, "USD")); + final Bid expectedBid = Bid.builder() + .adm("html") + .price(BigDecimal.TEN) + .cid("cid") + .w(1) + .h(2) + .impid("impId") + .id("bidId") + .crid("crid") + .build(); + assertThat(result.getValue()).containsExactly(BidderBid.of(expectedBid, banner, "seat", "USD")); } @Test - public void makeBidsShouldReturnErrorBidIfBidTypeIsAbsentInRequestImp() throws JsonProcessingException { + public void makeBidsShouldReturnVideoBidSuccessfully() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").build())) - .build(), - mapper.writeValueAsString( - givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + final BidderCall httpCall = givenHttpCall(givenBidResponse(bid -> bid + .cpm(BigDecimal.TEN) + .cid("cid") + .html("html") + .crid("crid") + .seat("seat") + .impId("impId") + .bidId("bidId") + .w("1") + .h("2"))); // when - final Result> result = target.makeBids(httpCall, null); + final Result> result = target.makeBids( + httpCall, + givenBidRequest(imp -> imp.id("impId").video(Video.builder().build()))); // then - assertThat(result.getErrors()).hasSize(1) - .extracting(BidderError::getMessage) - .containsExactly("Failed to find banner/video/audio impression 123"); - assertThat(result.getValue()).isEmpty(); + assertThat(result.getErrors()).isEmpty(); + final Bid expectedBid = Bid.builder() + .adm("html") + .price(BigDecimal.TEN) + .cid("cid") + .w(1) + .h(2) + .impid("impId") + .id("bidId") + .crid("crid") + .build(); + assertThat(result.getValue()).containsExactly(BidderBid.of(expectedBid, video, "seat", "USD")); } @Test - public void makeBidsShouldReturnErrorIfBidCurIsNotUsd() throws JsonProcessingException { + public void makeBidsShouldReturnAudioBidSuccessfully() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").build())) - .build(), - mapper.writeValueAsString(givenBidResponse(identity()).toBuilder().cur("EUR").build())); + final BidderCall httpCall = givenHttpCall(givenBidResponse(bid -> bid + .cpm(BigDecimal.TEN) + .cid("cid") + .html("html") + .crid("crid") + .seat("seat") + .impId("impId") + .bidId("bidId") + .w("1") + .h("2"))); // when - final Result> result = target.makeBids(httpCall, null); + final Result> result = target.makeBids( + httpCall, + givenBidRequest(imp -> imp.id("impId").audio(Audio.builder().build()))); // then - assertThat(result.getErrors()).hasSize(1) - .extracting(BidderError::getMessage) - .containsExactly("Bidder support only USD currency"); - assertThat(result.getValue()).isEmpty(); - } - - private static BidRequest givenBidRequest(UnaryOperator bidRequestCustomizer, - UnaryOperator impCustomizer) { - - return bidRequestCustomizer.apply(BidRequest.builder() - .imp(singletonList(givenImp(impCustomizer)))) + assertThat(result.getErrors()).isEmpty(); + final Bid expectedBid = Bid.builder() + .adm("html") + .price(BigDecimal.TEN) + .cid("cid") + .w(1) + .h(2) + .impid("impId") + .id("bidId") + .crid("crid") .build(); + assertThat(result.getValue()).containsExactly(BidderBid.of(expectedBid, audio, "seat", "USD")); } - private static BidRequest givenBidRequest(UnaryOperator impCustomizer) { - return givenBidRequest(identity(), impCustomizer); + private static BidRequest givenBidRequest(UnaryOperator... impCustomizers) { + return BidRequest.builder() + .imp(Stream.of(impCustomizers).map(ResetDigitalBidderTest::givenImp).toList()) + .build(); } private static Imp givenImp(UnaryOperator impCustomizer) { return impCustomizer.apply(Imp.builder() - .id("123") - .banner(Banner.builder().w(23).h(25).build())) + .id("impId") + .banner(Banner.builder().w(23).h(25).build()) + .ext(mapper.valueToTree(ExtPrebid.of( + null, + ExtImpResetDigital.of("placementId"))))) .build(); } - private static BidResponse givenBidResponse(UnaryOperator bidCustomizer) { - return BidResponse.builder() - .seatbid(singletonList(SeatBid.builder().bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) - .build())) - .cur("USD") - .build(); - } - - private static BidderCall givenHttpCall(BidRequest bidRequest, String body) { + private static BidderCall givenHttpCall(String body) { return BidderCall.succeededHttp( - HttpRequest.builder().payload(bidRequest).build(), + HttpRequest.builder().payload(null).build(), HttpResponse.of(200, null, body), null); } + + private String givenBidResponse(UnaryOperator... bidCustomizers) + throws JsonProcessingException { + + return mapper.writeValueAsString(ResetDigitalResponse.of( + Stream.of(bidCustomizers) + .map(bidCustomizer -> bidCustomizer.apply(ResetDigitalBid.builder()).build()) + .toList())); + } } diff --git a/src/test/java/org/prebid/server/bidder/vungle/VungleBidderTest.java b/src/test/java/org/prebid/server/bidder/vungle/VungleBidderTest.java index e609e2055f8..31967ae4523 100644 --- a/src/test/java/org/prebid/server/bidder/vungle/VungleBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/vungle/VungleBidderTest.java @@ -359,7 +359,7 @@ public void makeBidsShouldReturnVideoBidIfVideoIsPresentInRequestImp() throws Js // then assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) - .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), video, null)); + .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), video, "seat", null)); } @Test @@ -377,7 +377,7 @@ public void makeBidsShouldReturnVideoBidIfBaneerIsPresentInRequestImp() throws J // then assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) - .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), video, null)); + .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), video, "seat", null)); } private static BidRequest givenBidRequest( @@ -403,7 +403,9 @@ private static Imp givenImp(UnaryOperator impCustomizer) { private static BidResponse givenBidResponse(UnaryOperator bidCustomizer) { return BidResponse.builder() - .seatbid(singletonList(SeatBid.builder().bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .seatbid(singletonList(SeatBid.builder() + .seat("seat") + .bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) .build())) .build(); } diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItProcessedBidderResponseHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItProcessedBidderResponseHook.java index b626e03d5ac..d2c2066bb39 100644 --- a/src/test/java/org/prebid/server/it/hooks/SampleItProcessedBidderResponseHook.java +++ b/src/test/java/org/prebid/server/it/hooks/SampleItProcessedBidderResponseHook.java @@ -39,6 +39,7 @@ private List updateBids(List originalBids) { + "") .build(), bidderBid.getType(), + bidderBid.getSeat(), bidderBid.getBidCurrency())) .toList(); } diff --git a/src/test/java/org/prebid/server/it/hooks/SampleItRawBidderResponseHook.java b/src/test/java/org/prebid/server/it/hooks/SampleItRawBidderResponseHook.java index 0f30527519b..91b130382ed 100644 --- a/src/test/java/org/prebid/server/it/hooks/SampleItRawBidderResponseHook.java +++ b/src/test/java/org/prebid/server/it/hooks/SampleItRawBidderResponseHook.java @@ -39,6 +39,7 @@ private List updateBids(List originalBids) { + "") .build(), bidderBid.getType(), + bidderBid.getSeat(), bidderBid.getBidCurrency())) .toList(); } diff --git a/src/test/java/org/prebid/server/metric/MetricsTest.java b/src/test/java/org/prebid/server/metric/MetricsTest.java index 6f33ceab01f..243ef33e66d 100644 --- a/src/test/java/org/prebid/server/metric/MetricsTest.java +++ b/src/test/java/org/prebid/server/metric/MetricsTest.java @@ -682,6 +682,17 @@ public void updateSecureValidationMetricsShouldIncrementMetrics() { assertThat(metricRegistry.counter("account.accountId.response.validation.secure.err").getCount()).isEqualTo(2); } + @Test + public void updateSeatValidationMetricsShouldIncrementMetrics() { + // when + metrics.updateSeatValidationMetrics(RUBICON); + metrics.updateSeatValidationMetrics(CONVERSANT); + + // then + assertThat(metricRegistry.counter("adapter.rubicon.response.validation.seat").getCount()).isEqualTo(1); + assertThat(metricRegistry.counter("adapter.conversant.response.validation.seat").getCount()).isEqualTo(1); + } + @Test public void updateCookieSyncRequestMetricShouldIncrementMetric() { // when diff --git a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java index e2eb6a0d205..8c3cac67d8f 100644 --- a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java @@ -1326,48 +1326,6 @@ public void validateShouldReturnValidationMessageWhenAdjustmentMediaFactorNegati + "must be a positive number. Got -1.100000"); } - @Test - public void validateShouldReturnValidationMessageWhenBidderUnknown() { - // given - final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder().build(); - givenAdjustments.addFactor("unknownBidder", BigDecimal.valueOf(1.1F)); - final BidRequest bidRequest = validBidRequestBuilder() - .ext(ExtRequest.of( - ExtRequestPrebid.builder() - .bidadjustmentfactors(givenAdjustments) - .build())) - .build(); - - // when - final ValidationResult result = target.validate(Account.empty(ACCOUNT_ID), bidRequest, null, null); - - // then - assertThat(result.getErrors()).hasSize(1) - .containsOnly("request.ext.prebid.bidadjustmentfactors.unknownBidder is not a known bidder or alias"); - } - - @Test - public void validateShouldReturnValidationMessageWhenMediaBidderUnknown() { - // given - final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder() - .mediatypes(new EnumMap<>(Collections.singletonMap(ImpMediaType.xNative, - Collections.singletonMap("unknownBidder", BigDecimal.valueOf(1.1))))) - .build(); - final BidRequest bidRequest = validBidRequestBuilder() - .ext(ExtRequest.of( - ExtRequestPrebid.builder() - .bidadjustmentfactors(givenAdjustments) - .build())) - .build(); - // when - final ValidationResult result = target.validate(Account.empty(ACCOUNT_ID), bidRequest, null, null); - - // then - assertThat(result.getErrors()).hasSize(1) - .containsOnly( - "request.ext.prebid.bidadjustmentfactors.native.unknownBidder is not a known bidder or alias"); - } - @Test public void validateShouldReturnEmptyValidationMessagesWhenBidderIsKnownAndAdjustmentIsValid() { // given @@ -1414,29 +1372,6 @@ public void validateShouldReturnEmptyValidationMessagesWhenBidderIsKnownAliasFor assertThat(result.getErrors()).isEmpty(); } - @Test - public void validateShouldReturnEmptyValidationMessagesWhenBidderIsKnownBidderConfigAliasAndAdjustmentIsValid() { - // given - final String rubiconAlias = "rubicon_alias"; - final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder().build(); - givenAdjustments.addFactor(rubiconAlias, BigDecimal.valueOf(1.1)); - final BidRequest bidRequest = validBidRequestBuilder() - .ext(ExtRequest.of( - ExtRequestPrebid.builder() - .aliases(singletonMap(rubiconAlias, "rubicon")) - .bidadjustmentfactors(givenAdjustments) - .build())) - .build(); - - // when - final ValidationResult result = target.validate(Account.empty(ACCOUNT_ID), bidRequest, null, null); - - // then - verify(bidderCatalog).isValidName(rubiconAlias); - - assertThat(result.getErrors()).isEmpty(); - } - @Test public void validateShouldReturnValidationMessageWhenMultipleSchainsForSameBidder() { // given diff --git a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java index ffb6c9e6804..943a3fdbc42 100644 --- a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java @@ -21,12 +21,15 @@ import org.prebid.server.metric.Metrics; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountAlternateBidderCodes; +import org.prebid.server.settings.model.AccountAlternateBidderCodesBidder; import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.settings.model.AccountBidValidationConfig; import org.prebid.server.validation.model.ValidationResult; import java.math.BigDecimal; import java.util.Map; +import java.util.Set; import java.util.function.UnaryOperator; import static java.util.Arrays.asList; @@ -36,6 +39,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.BDDMockito.given; import static org.mockito.Mock.Strictness.LENIENT; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.prebid.server.settings.model.BidValidationEnforcement.enforce; @@ -522,6 +526,199 @@ public void validateShouldIncrementSecureValidationWarnMetrics() { verifyNoInteractions(bidRejectionTracker); } + @Test + public void validateShouldNotFailOnSeatValidationWhenSeatEqualsToBidder() { + // when + final ValidationResult result = target.validate( + givenBid(identity()).toBuilder().seat(BIDDER_NAME).build(), + BIDDER_NAME, + givenAuctionContext(), + bidderAliases); + + // then + assertThat(result.getWarnings()).isEmpty(); + assertThat(result.getErrors()).isEmpty(); + verify(metrics, never()).updateSeatValidationMetrics(BIDDER_NAME); + verifyNoInteractions(bidRejectionTracker); + } + + @Test + public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisabledForBidder() { + // given + final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); + + // when + final ValidationResult result = target.validate( + givenBid, + BIDDER_NAME, + givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( + AccountAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() + .enabled(false) + .allowedBidderCodes(Set.of("seat")) + .build())).build()))), + bidderAliases); + + // then + assertThat(result.getWarnings()) + .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); + assertThat(result.getErrors()).isEmpty(); + verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); + verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); + } + + @Test + public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLackingSeatAlternateCode() { + // given + final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); + + // when + final ValidationResult result = target.validate( + givenBid, + BIDDER_NAME, + givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( + AccountAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("anotherSeat")) + .build())).build()))), + bidderAliases); + + // then + assertThat(result.getWarnings()) + .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); + assertThat(result.getErrors()).isEmpty(); + verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); + verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); + } + + @Test + public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLackingBidder() { + // given + final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); + + // when + final ValidationResult result = target.validate( + givenBid, + BIDDER_NAME, + givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( + AccountAlternateBidderCodes.builder() + .enabled(true) + .bidders(null) + .build()))), + bidderAliases); + + // then + assertThat(result.getWarnings()) + .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); + assertThat(result.getErrors()).isEmpty(); + verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); + verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); + } + + @Test + public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisabled() { + // given + final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); + + // when + final ValidationResult result = target.validate( + givenBid, + BIDDER_NAME, + givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( + AccountAlternateBidderCodes.builder() + .enabled(false) + .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("seat")) + .build())).build()))), + bidderAliases); + + // then + assertThat(result.getWarnings()) + .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); + assertThat(result.getErrors()).isEmpty(); + verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); + verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); + } + + @Test + public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesAreNull() { + // given + final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); + + // when + final ValidationResult result = target.validate( + givenBid, + BIDDER_NAME, + givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( + AccountAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(null) + .build())).build()))), + bidderAliases); + + // then + assertThat(result.getWarnings()).isEmpty(); + assertThat(result.getErrors()).isEmpty(); + verify(metrics, never()).updateSeatValidationMetrics(BIDDER_NAME); + verifyNoInteractions(bidRejectionTracker); + } + + @Test + public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContainsWildcard() { + // given + final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); + + // when + final ValidationResult result = target.validate( + givenBid, + BIDDER_NAME, + givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( + AccountAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("*")) + .build())).build()))), + bidderAliases); + + // then + assertThat(result.getWarnings()).isEmpty(); + assertThat(result.getErrors()).isEmpty(); + verify(metrics, never()).updateSeatValidationMetrics(BIDDER_NAME); + verifyNoInteractions(bidRejectionTracker); + } + + @Test + public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContainsSeat() { + // given + final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); + + // when + final ValidationResult result = target.validate( + givenBid, + BIDDER_NAME, + givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( + AccountAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("seat")) + .build())).build()))), + bidderAliases); + + // then + assertThat(result.getWarnings()).isEmpty(); + assertThat(result.getErrors()).isEmpty(); + verify(metrics, never()).updateSeatValidationMetrics(BIDDER_NAME); + verifyNoInteractions(bidRejectionTracker); + } + private BidRequest givenRequest(UnaryOperator impCustomizer) { final ObjectNode ext = mapper.createObjectNode().set( "prebid", mapper.createObjectNode().set( diff --git a/src/test/resources/org/prebid/server/it/amp/test-cache-request.json b/src/test/resources/org/prebid/server/it/amp/test-cache-request.json index fe8eba5c934..8f94e6c3fc8 100644 --- a/src/test/resources/org/prebid/server/it/amp/test-cache-request.json +++ b/src/test/resources/org/prebid/server/it/amp/test-cache-request.json @@ -12,7 +12,10 @@ "h": 600, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "generic" + } }, "rp": { "targeting": [ @@ -48,7 +51,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "genericAlias" + } }, "genericAlias": { "brand_id": 1, diff --git a/src/test/resources/org/prebid/server/it/cache/update/test-auction-response.json b/src/test/resources/org/prebid/server/it/cache/update/test-auction-response.json index e6127bea4f0..6b1a866f018 100644 --- a/src/test/resources/org/prebid/server/it/cache/update/test-auction-response.json +++ b/src/test/resources/org/prebid/server/it/cache/update/test-auction-response.json @@ -15,6 +15,9 @@ "ext": { "prebid": { "type": "banner", + "meta": { + "adaptercode": "generic" + }, "targeting": { "hb_pb": "4.20", "hb_pb_generic": "4.20", @@ -45,6 +48,9 @@ "ext": { "prebid": { "type": "video", + "meta": { + "adaptercode": "genericAlias" + }, "targeting": { "hb_pb": "3.00", "hb_pb_genericAlias": "3.00", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/33across/test-auction-33across-response.json b/src/test/resources/org/prebid/server/it/openrtb2/33across/test-auction-33across-response.json index b7a0ac4311d..cde627280fa 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/33across/test-auction-33across-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/33across/test-auction-33across-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "33across" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/aax/test-auction-aax-response.json b/src/test/resources/org/prebid/server/it/openrtb2/aax/test-auction-aax-response.json index f6f8aa08087..b15064c49c2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/aax/test-auction-aax-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/aax/test-auction-aax-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "aax" + } }, "origbidcpm": 0.5, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/aceex/test-auction-aceex-response.json b/src/test/resources/org/prebid/server/it/openrtb2/aceex/test-auction-aceex-response.json index b9b61a696c0..d01603ad742 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/aceex/test-auction-aceex-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/aceex/test-auction-aceex-response.json @@ -13,7 +13,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "aceex" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-auction-acuityads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-auction-acuityads-response.json index a0bab7d6cc2..42131d2826a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-auction-acuityads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-auction-acuityads-response.json @@ -13,7 +13,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "acuityads" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adelement/test-auction-adelement-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adelement/test-auction-adelement-response.json index 0c48f3a8431..5e53a30ee9a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adelement/test-auction-adelement-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adelement/test-auction-adelement-response.json @@ -17,7 +17,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adelement" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adf/test-auction-adf-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adf/test-auction-adf-response.json index f4417095fa3..70a4616692e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adf/test-auction-adf-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adf/test-auction-adf-response.json @@ -13,7 +13,10 @@ "crid": "test-creative-id-1", "ext": { "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "adf" + } }, "pt": "gross", "origbidcpm": 10, @@ -30,7 +33,10 @@ "crid": "test-creative-id-2", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adf" + } }, "pt": "gross", "origbidcpm": 10, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-auction-adgeneration-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-auction-adgeneration-response.json index 25ebe533dcc..81ddb4c26b9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-auction-adgeneration-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-auction-adgeneration-response.json @@ -15,7 +15,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adgeneration" + } }, "origbidcpm": 46.6, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-auction-adhese-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-auction-adhese-response.json index f5fd5214de2..2b538c0f78d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-auction-adhese-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-auction-adhese-response.json @@ -24,7 +24,10 @@ "origbidcpm": 2.184, "origbidcur": "USD", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adhese" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-auction-adkernel-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-auction-adkernel-response.json index a6a8e2bd0c8..ee54b00b505 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-auction-adkernel-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-auction-adkernel-response.json @@ -18,7 +18,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adkernel" + } }, "origbidcpm": 2.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-auction-adkerneladn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-auction-adkerneladn-response.json index 9563c1ff672..b93c9596668 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-auction-adkerneladn-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-auction-adkerneladn-response.json @@ -22,7 +22,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adkernelAdn" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-auction-adman-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-auction-adman-response.json index 8884760961e..6c12865d18e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-auction-adman-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-auction-adman-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adman" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/admatic/test-auction-admatic-response.json b/src/test/resources/org/prebid/server/it/openrtb2/admatic/test-auction-admatic-response.json index 0277bb7f78d..cb9952334cc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/admatic/test-auction-admatic-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/admatic/test-auction-admatic-response.json @@ -13,7 +13,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "admatic" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-auction-admixer-response.json b/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-auction-admixer-response.json index 75f33a522f6..5294abfff5c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-auction-admixer-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-auction-admixer-response.json @@ -10,7 +10,10 @@ "ext": { "format": "BANNER", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "admixer" + } }, "origbidcpm": 0.01 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adnuntius/test-auction-adnuntius-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adnuntius/test-auction-adnuntius-response.json index 61bac864a49..6d033a9c208 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adnuntius/test-auction-adnuntius-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adnuntius/test-auction-adnuntius-response.json @@ -20,7 +20,10 @@ "h": 90, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adnuntius" + } }, "origbidcpm": 42420.00, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-auction-adocean-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-auction-adocean-response.json index 3f62c1fb7db..ea7c23c5bb4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-auction-adocean-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-auction-adocean-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adocean" + } }, "origbidcpm": 10, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-auction-adoppler-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-auction-adoppler-response.json index 7822b00cdbb..cbfeaa10b25 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-auction-adoppler-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-auction-adoppler-response.json @@ -18,7 +18,10 @@ ], "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adoppler" + } }, "origbidcpm": 3.33, "ads": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adot/test-auction-adot-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adot/test-auction-adot-response.json index b2c52bb7d9e..fd3bea140aa 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adot/test-auction-adot-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adot/test-auction-adot-response.json @@ -18,7 +18,10 @@ }, "origbidcpm": 1.16346, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adot" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-auction-adpone-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-auction-adpone-response.json index 3c4fc34a311..cb895905e04 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-auction-adpone-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-auction-adpone-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adpone" + } }, "origbidcpm": 6.66 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-auction-adprime-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-auction-adprime-response.json index 073a812bcdb..59fcbbbfc93 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-auction-adprime-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-auction-adprime-response.json @@ -15,7 +15,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adprime" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adquery/test-auction-adquery-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adquery/test-auction-adquery-response.json index 1d301f75624..eaacefd6e37 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adquery/test-auction-adquery-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adquery/test-auction-adquery-response.json @@ -19,7 +19,10 @@ "origbidcpm": 4.14, "origbidcur": "PLN", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adquery" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adrino/test-auction-adrino-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adrino/test-auction-adrino-response.json index e1341dbdcca..fe0402359f2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adrino/test-auction-adrino-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adrino/test-auction-adrino-response.json @@ -15,7 +15,10 @@ "h": 250, "ext": { "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "adrino" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adsyield/test-auction-adsyield-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adsyield/test-auction-adsyield-response.json index 855d418643f..7a0e6a0da88 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adsyield/test-auction-adsyield-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adsyield/test-auction-adsyield-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adsyield" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-auction-adtarget-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-auction-adtarget-response.json index 809b063e228..536240551f1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-auction-adtarget-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-auction-adtarget-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adtarget" + } }, "origbidcpm": 8.43 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-auction-adtelligent-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-auction-adtelligent-response.json index b73512ad65c..fef8a263859 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-auction-adtelligent-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-auction-adtelligent-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adtelligent" + } }, "origbidcpm": 8.43 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtonos/test-auction-adtonos-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adtonos/test-auction-adtonos-response.json index c5bfdb6d592..3258c4cc98b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtonos/test-auction-adtonos-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtonos/test-auction-adtonos-response.json @@ -13,7 +13,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adtonos" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtrgtme/test-auction-adtrgtme-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adtrgtme/test-auction-adtrgtme-response.json index d786080f717..76d53b3e7c3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtrgtme/test-auction-adtrgtme-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtrgtme/test-auction-adtrgtme-response.json @@ -14,7 +14,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adtrgtme" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-auction-advangelists-response.json b/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-auction-advangelists-response.json index 92ba70c5c42..0253ead2b9a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-auction-advangelists-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-auction-advangelists-response.json @@ -13,7 +13,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "advangelists" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adview/test-auction-adview-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adview/test-auction-adview-response.json index a6c118e0913..9c24d558743 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adview/test-auction-adview-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adview/test-auction-adview-response.json @@ -15,7 +15,10 @@ "ext": { "origbidcpm": 0.01, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adview" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adxcg/test-auction-adxcg-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adxcg/test-auction-adxcg-response.json index 0961b1f67ec..9e0135219f3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adxcg/test-auction-adxcg-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adxcg/test-auction-adxcg-response.json @@ -17,7 +17,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adxcg" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-response.json index 96aa18de5d8..1c403a36179 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adyoulike" + } }, "origbidcpm": 3.33, "origbidcur" : "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/aidem/test-auction-aidem-response.json b/src/test/resources/org/prebid/server/it/openrtb2/aidem/test-auction-aidem-response.json index f5ee4e08e9c..5d681f38d56 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/aidem/test-auction-aidem-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/aidem/test-auction-aidem-response.json @@ -13,7 +13,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "aidem" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-auction-aja-response.json b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-auction-aja-response.json index 7010f75f5e6..42fbe4116e3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-auction-aja-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-auction-aja-response.json @@ -17,7 +17,10 @@ "ext": { "origbidcpm": 10, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "aja" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/algorix/test-auction-algorix-response.json b/src/test/resources/org/prebid/server/it/openrtb2/algorix/test-auction-algorix-response.json index b61aebbccd6..f9ede300eb2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/algorix/test-auction-algorix-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/algorix/test-auction-algorix-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "algorix" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/alkimi/test-auction-alkimi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/alkimi/test-auction-alkimi-response.json index b8ccdb2d3b3..19a0d9f4f3a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/alkimi/test-auction-alkimi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/alkimi/test-auction-alkimi-response.json @@ -15,7 +15,10 @@ "nurl": "https://example.com/nurl", "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "alkimi" + } }, "origbidcpm": 1 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-response.json index ec393ab7ca0..fc1daacf1f9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-response.json @@ -15,7 +15,10 @@ "nurl": "nurl001", "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "amx" + } }, "origbidcpm": 0.01, "ct": 0, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/apacdex/test-auction-apacdex-response.json b/src/test/resources/org/prebid/server/it/openrtb2/apacdex/test-auction-apacdex-response.json index 2122bfc623a..e309156e72f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/apacdex/test-auction-apacdex-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/apacdex/test-auction-apacdex-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "apacdex" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/appush/test-auction-appush-response.json b/src/test/resources/org/prebid/server/it/openrtb2/appush/test-auction-appush-response.json index f673f770ad2..6c5b20129bf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/appush/test-auction-appush-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/appush/test-auction-appush-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "appush" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/aso/test-auction-aso-response.json b/src/test/resources/org/prebid/server/it/openrtb2/aso/test-auction-aso-response.json index 6b9a19e7187..7670fae5f7f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/aso/test-auction-aso-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/aso/test-auction-aso-response.json @@ -13,7 +13,10 @@ "crid": "crid6", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "aso" + } }, "origbidcpm": 4.7 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/audiencenetwork/test-auction-audiencenetwork-response.json b/src/test/resources/org/prebid/server/it/openrtb2/audiencenetwork/test-auction-audiencenetwork-response.json index e1d18a2ecb5..2f513a5ee51 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/audiencenetwork/test-auction-audiencenetwork-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/audiencenetwork/test-auction-audiencenetwork-response.json @@ -15,7 +15,10 @@ "h": 50, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "audienceNetwork" + } }, "origbidcpm": 9.0 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/automatad/test-auction-automatad-response.json b/src/test/resources/org/prebid/server/it/openrtb2/automatad/test-auction-automatad-response.json index c4c971e466e..5d1340fba78 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/automatad/test-auction-automatad-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/automatad/test-auction-automatad-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "automatad" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-auction-avocet-response.json b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-auction-avocet-response.json index 6fca036d997..d74e2cf643b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-auction-avocet-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-auction-avocet-response.json @@ -23,7 +23,10 @@ "duration": 30 }, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "avocet" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/axis/test-auction-axis-response.json b/src/test/resources/org/prebid/server/it/openrtb2/axis/test-auction-axis-response.json index 676eb7d802a..cf54843f074 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/axis/test-auction-axis-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/axis/test-auction-axis-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "axis" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/axonix/test-auction-axonix-response.json b/src/test/resources/org/prebid/server/it/openrtb2/axonix/test-auction-axonix-response.json index e0e02fc7381..644897f8e35 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/axonix/test-auction-axonix-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/axonix/test-auction-axonix-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "axonix" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bcmint/test-auction-bcmint-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bcmint/test-auction-bcmint-response.json index c591ef97cfd..9f6384c7795 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bcmint/test-auction-bcmint-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bcmint/test-auction-bcmint-response.json @@ -13,7 +13,10 @@ "crid": "crid6", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bcmint" + } }, "origbidcpm": 4.7 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-auction-beachfront-response.json b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-auction-beachfront-response.json index 5e10a21b5de..f65afc48130 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-auction-beachfront-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-auction-beachfront-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "beachfront" + } }, "origbidcpm": 2.942807912826538, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-response.json b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-response.json index bed5b0e3939..c0e516408b2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "beintoo" + } }, "origbidcpm": 2.942808, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bematterfull/test-auction-bematterfull-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bematterfull/test-auction-bematterfull-response.json index 1d2bac9f898..5163e685fe7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bematterfull/test-auction-bematterfull-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bematterfull/test-auction-bematterfull-response.json @@ -12,7 +12,10 @@ "crid": "crid6", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bematterfull" + } }, "origbidcpm": 4.7 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/between/test-auction-between-response.json b/src/test/resources/org/prebid/server/it/openrtb2/between/test-auction-between-response.json index cf2a6e0d031..731eaca081a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/between/test-auction-between-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/between/test-auction-between-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "between" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beyondmedia/test-auction-beyondmedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/beyondmedia/test-auction-beyondmedia-response.json index e63089babb2..7f8969fa554 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beyondmedia/test-auction-beyondmedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beyondmedia/test-auction-beyondmedia-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "beyondmedia" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bidagency/test-auction-bidagency-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bidagency/test-auction-bidagency-response.json index fdba12487c7..0f9f64d5403 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bidagency/test-auction-bidagency-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bidagency/test-auction-bidagency-response.json @@ -13,7 +13,10 @@ "crid": "crid6", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bidagency" + } }, "origbidcpm": 4.7 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bidmachine/test-auction-bidmachine-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bidmachine/test-auction-bidmachine-response.json index 0ea56280b80..34cb407ea7f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bidmachine/test-auction-bidmachine-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bidmachine/test-auction-bidmachine-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bidmachine" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bidmatic/test-auction-bidmatic-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bidmatic/test-auction-bidmatic-response.json index ba0b73cfaf1..ea2ddc26844 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bidmatic/test-auction-bidmatic-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bidmatic/test-auction-bidmatic-response.json @@ -15,7 +15,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bidmatic" + } }, "origbidcpm": 8.43 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bidmyadz/test-auction-bidmyadz-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bidmyadz/test-auction-bidmyadz-response.json index 399a568d088..633ba502bd4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bidmyadz/test-auction-bidmyadz-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bidmyadz/test-auction-bidmyadz-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bidmyadz" + } }, "mediaType": "banner", "origbidcpm": 3.33 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bidscube/test-auction-bidscube-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bidscube/test-auction-bidscube-response.json index 8c8b0128e98..13b44ba7e75 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bidscube/test-auction-bidscube-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bidscube/test-auction-bidscube-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bidscube" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bidstack/test-auction-bidstack-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bidstack/test-auction-bidstack-response.json index 9428b19fd0a..6897c027859 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bidstack/test-auction-bidstack-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bidstack/test-auction-bidstack-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "bidstack" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bigoad/test-auction-bigoad-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bigoad/test-auction-bigoad-response.json index 013cd170712..8440c97bcb3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bigoad/test-auction-bigoad-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bigoad/test-auction-bigoad-response.json @@ -17,7 +17,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bigoad" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/blasto/test-auction-blasto-response.json b/src/test/resources/org/prebid/server/it/openrtb2/blasto/test-auction-blasto-response.json index 22a67229971..ed8c5305e03 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/blasto/test-auction-blasto-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/blasto/test-auction-blasto-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "blasto" + } }, "origbidcur": "USD", "origbidcpm": 3.33 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bliink/test-auction-bliink-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bliink/test-auction-bliink-response.json index f4ddf9222af..1a70759e914 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bliink/test-auction-bliink-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bliink/test-auction-bliink-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bliink" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/blue/test-auction-blue-response.json b/src/test/resources/org/prebid/server/it/openrtb2/blue/test-auction-blue-response.json index f241baedf4c..897aed832f7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/blue/test-auction-blue-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/blue/test-auction-blue-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "blue" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bluesea/test-auction-bluesea-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bluesea/test-auction-bluesea-response.json index 71412aa8e6c..a855aaabb71 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bluesea/test-auction-bluesea-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bluesea/test-auction-bluesea-response.json @@ -15,7 +15,10 @@ "ext": { "mediatype":"banner", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bluesea" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bmtm/test-auction-bmtm-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bmtm/test-auction-bmtm-response.json index cbbae431606..ab990f9727a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bmtm/test-auction-bmtm-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bmtm/test-auction-bmtm-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bmtm" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/boldwin/test-auction-boldwin-response.json b/src/test/resources/org/prebid/server/it/openrtb2/boldwin/test-auction-boldwin-response.json index 4d5d8f5ce9e..8c800af18a4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/boldwin/test-auction-boldwin-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/boldwin/test-auction-boldwin-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "boldwin" + } }, "origbidcpm": 1.25 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/brave/test-auction-brave-response.json b/src/test/resources/org/prebid/server/it/openrtb2/brave/test-auction-brave-response.json index 43de8398d78..749db2a5fdb 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/brave/test-auction-brave-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/brave/test-auction-brave-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "brave" + } }, "origbidcur": "USD", "origbidcpm": 0.01 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/bwx/test-auction-bwx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/bwx/test-auction-bwx-response.json index 6107fe586a3..91c952abb28 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/bwx/test-auction-bwx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/bwx/test-auction-bwx-response.json @@ -14,7 +14,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "bwx" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/cadentaperturemx/test-auction-cadentaperturemx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/cadentaperturemx/test-auction-cadentaperturemx-response.json index f2f43ba2c1d..f6efa7130f2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/cadentaperturemx/test-auction-cadentaperturemx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/cadentaperturemx/test-auction-cadentaperturemx-response.json @@ -15,7 +15,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "cadent_aperture_mx" + } }, "origbidcpm": 2.942808, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ccx/test-auction-ccx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ccx/test-auction-ccx-response.json index 7fcafb472c7..f285ee8bfca 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ccx/test-auction-ccx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ccx/test-auction-ccx-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "ccx" + } }, "type": "standard" }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/cointraffic/test-auction-cointraffic-response.json b/src/test/resources/org/prebid/server/it/openrtb2/cointraffic/test-auction-cointraffic-response.json index 06fadbf0b09..6b6d3e48a42 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/cointraffic/test-auction-cointraffic-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/cointraffic/test-auction-cointraffic-response.json @@ -13,7 +13,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "cointraffic" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/coinzilla/test-auction-coinzilla-response.json b/src/test/resources/org/prebid/server/it/openrtb2/coinzilla/test-auction-coinzilla-response.json index 9f59c942b28..c324ea7e396 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/coinzilla/test-auction-coinzilla-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/coinzilla/test-auction-coinzilla-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "coinzilla" + } }, "origbidcpm": 6.66 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/colossus/aliases/test-auction-colossusssp-response.json b/src/test/resources/org/prebid/server/it/openrtb2/colossus/aliases/test-auction-colossusssp-response.json index f551e12bbe4..a7561797cd2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/colossus/aliases/test-auction-colossusssp-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/colossus/aliases/test-auction-colossusssp-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "colossusssp" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-auction-colossus-response.json b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-auction-colossus-response.json index d7914b5fb58..00b82c6832c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-auction-colossus-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-auction-colossus-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "colossus" + } }, "mediaType" : "banner", "origbidcpm": 1.25 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/compass/test-auction-compass-response.json b/src/test/resources/org/prebid/server/it/openrtb2/compass/test-auction-compass-response.json index 20f86d6a348..8d99466cf31 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/compass/test-auction-compass-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/compass/test-auction-compass-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "compass" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/concert/test-auction-concert-response.json b/src/test/resources/org/prebid/server/it/openrtb2/concert/test-auction-concert-response.json index 666a177b9c1..0bf7901ecec 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/concert/test-auction-concert-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/concert/test-auction-concert-response.json @@ -17,7 +17,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "concert" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-auction-connectad-response.json b/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-auction-connectad-response.json index d24913feeef..e797ec6a137 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-auction-connectad-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-auction-connectad-response.json @@ -14,7 +14,10 @@ "ext": { "format": "BANNER", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "connectad" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/connektai/test-auction-connektai-response.json b/src/test/resources/org/prebid/server/it/openrtb2/connektai/test-auction-connektai-response.json index 66239692835..14df1f1c64d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/connektai/test-auction-connektai-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/connektai/test-auction-connektai-response.json @@ -14,7 +14,10 @@ "crid": "test-creative-id-1", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "connektai" + } }, "origbidcpm": 10, "origbidcur": "EUR" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-auction-consumable-response.json b/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-auction-consumable-response.json index a28d27cf14a..08b04afa02b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-auction-consumable-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-auction-consumable-response.json @@ -18,7 +18,10 @@ "origbidcpm": 0.5, "origbidcur": "USD", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "consumable" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/copper6/test-auction-copper6-response.json b/src/test/resources/org/prebid/server/it/openrtb2/copper6/test-auction-copper6-response.json index 3ac3ccb1672..a0761e1f8f5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/copper6/test-auction-copper6-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/copper6/test-auction-copper6-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "copper6" + } }, "origbidcpm": 8.43 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/copper6ssp/test-auction-copper6ssp-response.json b/src/test/resources/org/prebid/server/it/openrtb2/copper6ssp/test-auction-copper6ssp-response.json index 52b36682c8a..5568f0c15de 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/copper6ssp/test-auction-copper6ssp-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/copper6ssp/test-auction-copper6ssp-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "copper6ssp" + } }, "origbidcpm": 1.25 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-auction-cpmstar-response.json b/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-auction-cpmstar-response.json index 6a685a06ba4..c3dbd66dd05 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-auction-cpmstar-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-auction-cpmstar-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "cpmstar" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/criteo/test-auction-criteo-response.json b/src/test/resources/org/prebid/server/it/openrtb2/criteo/test-auction-criteo-response.json index 9d7e6b1ca5b..0968661be88 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/criteo/test-auction-criteo-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/criteo/test-auction-criteo-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "criteo" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/cwire/test-auction-cwire-response.json b/src/test/resources/org/prebid/server/it/openrtb2/cwire/test-auction-cwire-response.json index ba9923d657c..be6517f1b26 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/cwire/test-auction-cwire-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/cwire/test-auction-cwire-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "cwire" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-response.json b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-response.json index a73407d0bb8..93ee48f70a3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "datablocks" + } }, "origbidcpm": 7.77 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-response.json index 6b058b84507..84a45888fd2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "decenterads" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-response.json b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-response.json index 223095836df..26021d2b4cf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-response.json @@ -13,7 +13,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "deepintent" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/definemedia/test-auction-definemedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/definemedia/test-auction-definemedia-response.json index 34d7cd3fbf2..381bc91c43e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/definemedia/test-auction-definemedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/definemedia/test-auction-definemedia-response.json @@ -13,7 +13,10 @@ "crid": "test-creative-id-1", "ext": { "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "definemedia" + } }, "origbidcpm": 10, "origbidcur": "EUR" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/dianomi/test-auction-dianomi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/dianomi/test-auction-dianomi-response.json index 0725b710372..3ce055440ed 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/dianomi/test-auction-dianomi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/dianomi/test-auction-dianomi-response.json @@ -13,7 +13,10 @@ "crid": "test-creative-id-2", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "dianomi" + } }, "pt": "gross", "origbidcpm": 10, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/dianomi/test-dianomi-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/dianomi/test-dianomi-bid-response.json index eabb1b30546..f4d5e5d39d9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/dianomi/test-dianomi-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/dianomi/test-dianomi-bid-response.json @@ -12,7 +12,10 @@ "crid": "test-creative-id-2", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "gross" + } }, "pt": "gross" } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/displayio/test-auction-displayio-response.json b/src/test/resources/org/prebid/server/it/openrtb2/displayio/test-auction-displayio-response.json index ad84acca12c..bdb825cec4c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/displayio/test-auction-displayio-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/displayio/test-auction-displayio-response.json @@ -14,7 +14,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "displayio" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-response.json index e7b10ebdda4..d330b13d7f2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-response.json @@ -13,7 +13,10 @@ "ext": { "format": "BANNER", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "dmx" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/driftpixel/test-auction-driftpixel-response.json b/src/test/resources/org/prebid/server/it/openrtb2/driftpixel/test-auction-driftpixel-response.json index d28852c4ccd..277f808bce6 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/driftpixel/test-auction-driftpixel-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/driftpixel/test-auction-driftpixel-response.json @@ -14,7 +14,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "driftpixel" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/dxkulture/test-auction-dxkulture-response.json b/src/test/resources/org/prebid/server/it/openrtb2/dxkulture/test-auction-dxkulture-response.json index b2442775de6..5756bce1878 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/dxkulture/test-auction-dxkulture-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/dxkulture/test-auction-dxkulture-response.json @@ -13,7 +13,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "dxkulture" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/edge226/test-auction-edge226-response.json b/src/test/resources/org/prebid/server/it/openrtb2/edge226/test-auction-edge226-response.json index 2b9d8f83ca4..ba20d1a291a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/edge226/test-auction-edge226-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/edge226/test-auction-edge226-response.json @@ -14,7 +14,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "edge226" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/embimedia/test-auction-embimedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/embimedia/test-auction-embimedia-response.json index 930aa7c8b06..baeaf2c7c8c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/embimedia/test-auction-embimedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/embimedia/test-auction-embimedia-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "embimedia" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/emtv/test-auction-emtv-response.json b/src/test/resources/org/prebid/server/it/openrtb2/emtv/test-auction-emtv-response.json index 3795c5a9c62..a1e1b4586a6 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/emtv/test-auction-emtv-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/emtv/test-auction-emtv-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "emtv" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-auction-emxdigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-auction-emxdigital-response.json index 552b0f3a934..0c7409ad7f1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-auction-emxdigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-auction-emxdigital-response.json @@ -15,7 +15,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "emx_digital" + } }, "origbidcpm": 2.942808, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-auction-eplanning-response.json b/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-auction-eplanning-response.json index ce65aba9a9b..aee270657c9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-auction-eplanning-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-auction-eplanning-response.json @@ -16,7 +16,10 @@ "ext": { "origbidcpm": 0.5, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "eplanning" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-response.json b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-response.json index f10ab8e286e..f6922d0abf4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "epom" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/epsilon/alias/test-auction-epsilon-response.json b/src/test/resources/org/prebid/server/it/openrtb2/epsilon/alias/test-auction-epsilon-response.json index 3dd393badc9..99c0ed3bfce 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/epsilon/alias/test-auction-epsilon-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/epsilon/alias/test-auction-epsilon-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "conversant" + } }, "origbidcpm": 5.0 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/epsilon/test-auction-epsilon-response.json b/src/test/resources/org/prebid/server/it/openrtb2/epsilon/test-auction-epsilon-response.json index 4aa8c6d0985..1331eadb2b9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/epsilon/test-auction-epsilon-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/epsilon/test-auction-epsilon-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "epsilon" + } }, "origbidcpm": 6.0 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/escalax/test-auction-escalax-response.json b/src/test/resources/org/prebid/server/it/openrtb2/escalax/test-auction-escalax-response.json index 7f2babf609e..197c5aeb8c0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/escalax/test-auction-escalax-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/escalax/test-auction-escalax-response.json @@ -15,7 +15,10 @@ "mtype": 2, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "escalax" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/evolution/test-auction-evolution-response.json b/src/test/resources/org/prebid/server/it/openrtb2/evolution/test-auction-evolution-response.json index d0043247edf..af999a6b058 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/evolution/test-auction-evolution-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/evolution/test-auction-evolution-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "e_volution" + } }, "mediaType": "banner", "origbidcpm": 3.33 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/felixads/test-auction-felixads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/felixads/test-auction-felixads-response.json index 0b63bd03f57..28796b6b966 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/felixads/test-auction-felixads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/felixads/test-auction-felixads-response.json @@ -18,7 +18,10 @@ "mediaType": "video", "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "felixads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/filmzie/test-auction-filmzie-response.json b/src/test/resources/org/prebid/server/it/openrtb2/filmzie/test-auction-filmzie-response.json index e2c3508d1ab..b56413dc9a0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/filmzie/test-auction-filmzie-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/filmzie/test-auction-filmzie-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "filmzie" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/finative/test-auction-finative-response.json b/src/test/resources/org/prebid/server/it/openrtb2/finative/test-auction-finative-response.json index e055b56bb65..33e56e2c057 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/finative/test-auction-finative-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/finative/test-auction-finative-response.json @@ -14,7 +14,10 @@ "crid": "test-creative-id-1", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "finative" + } }, "origbidcpm": 10, "origbidcur": "EUR" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/flipp/test-auction-flipp-response.json b/src/test/resources/org/prebid/server/it/openrtb2/flipp/test-auction-flipp-response.json index a79558cbd9f..6de3f2adc6a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/flipp/test-auction-flipp-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/flipp/test-auction-flipp-response.json @@ -16,7 +16,10 @@ "origbidcpm": 12.34, "origbidcur": "USD", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "flipp" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/floors/floors-test-auction-response-no-signal.json b/src/test/resources/org/prebid/server/it/openrtb2/floors/floors-test-auction-response-no-signal.json index bc2278e74a3..09b7be0add3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/floors/floors-test-auction-response-no-signal.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/floors/floors-test-auction-response-no-signal.json @@ -12,7 +12,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "generic" + } }, "origbidcpm": 13, "origbidcur": "GBP" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/floors/floors-test-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/floors/floors-test-auction-response.json index 179a08e5cb1..d74037d285a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/floors/floors-test-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/floors/floors-test-auction-response.json @@ -12,7 +12,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "generic" + } }, "origbidcpm": 13, "origbidcur":"GBP" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/freewheelssp/test-auction-freewheelssp-response.json b/src/test/resources/org/prebid/server/it/openrtb2/freewheelssp/test-auction-freewheelssp-response.json index d583e32cc4f..0ad3c8e2466 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/freewheelssp/test-auction-freewheelssp-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/freewheelssp/test-auction-freewheelssp-response.json @@ -14,7 +14,10 @@ "crid": "7857", "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "freewheelssp" + } }, "origbidcpm": 1 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/frvradn/test-auction-frvradn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/frvradn/test-auction-frvradn-response.json index 683c42863d0..c9aaea5890b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/frvradn/test-auction-frvradn-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/frvradn/test-auction-frvradn-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "frvradn" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-auction-gamma-response.json b/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-auction-gamma-response.json index ce0e41775aa..6890852a1da 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-auction-gamma-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-auction-gamma-response.json @@ -19,7 +19,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "gamma" + } }, "origbidcpm": 0.5, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-auction-gamoshi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-auction-gamoshi-response.json index 4d6ea3f9060..5d1b6d4f355 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-auction-gamoshi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-auction-gamoshi-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "gamoshi" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/generic/test-auction-generic-response.json b/src/test/resources/org/prebid/server/it/openrtb2/generic/test-auction-generic-response.json index 8f2d2e4407c..5d0d9e49553 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/generic/test-auction-generic-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/generic/test-auction-generic-response.json @@ -15,7 +15,7 @@ "type": "banner", "meta": { "mediaType": "banner", - "adaptercode": "adaptercode" + "adaptercode": "generic" } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-response.json b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-response.json index 4ee1ff6a6c8..5aac6629309 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-auction-generic-response.json @@ -55,7 +55,8 @@ "rendererData": { "data": "some data" }, - "rendererUrl": "rendererUrl" + "rendererUrl": "rendererUrl", + "adaptercode": "generic" } }, "origbidcpm": 3.33 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-cache-generic-request.json b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-cache-generic-request.json index a6d65dfcae0..aa611ad083c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-cache-generic-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/generic_core_functionality/test-cache-generic-request.json @@ -30,7 +30,8 @@ "rendererData": { "data": "some data" }, - "rendererUrl": "rendererUrl" + "rendererUrl": "rendererUrl", + "adaptercode": "generic" } }, "origbidcpm": 3.33 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/globalsun/test-auction-globalsun-response.json b/src/test/resources/org/prebid/server/it/openrtb2/globalsun/test-auction-globalsun-response.json index 505a3ca4b5c..bbf696d0d99 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/globalsun/test-auction-globalsun-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/globalsun/test-auction-globalsun-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "globalsun" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gothamads/test-auction-gothamads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/gothamads/test-auction-gothamads-response.json index 728dccb2b13..b7439b4fb7a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gothamads/test-auction-gothamads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gothamads/test-auction-gothamads-response.json @@ -14,7 +14,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "gothamads" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/greedygame/test-auction-greedygame-response.json b/src/test/resources/org/prebid/server/it/openrtb2/greedygame/test-auction-greedygame-response.json index 7d19f2a3f5c..0a31a380e73 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/greedygame/test-auction-greedygame-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/greedygame/test-auction-greedygame-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "greedygame" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json index f6a034ca8a3..eef83d5e402 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json @@ -18,7 +18,8 @@ "prebid": { "type": "banner", "meta": { - "demandSource": "trustx" + "demandSource": "trustx", + "adaptercode": "grid" } }, "origbidcpm": 3.33 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-response.json b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-response.json index 7c131a1f180..76e63e1666c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-response.json @@ -14,7 +14,10 @@ "crid": "crid001", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "gumgum" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_app_promotion_type/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_app_promotion_type/test-huaweiads-auction-response.json index 2068eb254c5..b2422c4ed4b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_app_promotion_type/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_app_promotion_type/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_ch_endpoint/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_ch_endpoint/test-huaweiads-auction-response.json index 931449bc021..76e68233f75 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_ch_endpoint/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_ch_endpoint/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_eu_endpoint/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_eu_endpoint/test-huaweiads-auction-response.json index 931449bc021..76e68233f75 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_eu_endpoint/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_eu_endpoint/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_imei/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_imei/test-huaweiads-auction-response.json index 931449bc021..76e68233f75 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_imei/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_imei/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_interstitial_type/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_interstitial_type/test-huaweiads-auction-response.json index 3f3b9084e45..40bfe76cd7c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_interstitial_type/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_interstitial_type/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_mccmnc/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_mccmnc/test-huaweiads-auction-response.json index d6d29d2c614..760903a05d1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_mccmnc/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_mccmnc/test-huaweiads-auction-response.json @@ -23,7 +23,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } }, "h": 250, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_non_integer_mccmnc/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_non_integer_mccmnc/test-huaweiads-auction-response.json index d6d29d2c614..760903a05d1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_non_integer_mccmnc/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_non_integer_mccmnc/test-huaweiads-auction-response.json @@ -23,7 +23,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } }, "h": 250, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_not_app_promotion_type/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_not_app_promotion_type/test-huaweiads-auction-response.json index 05a00845f55..5543b401836 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_not_app_promotion_type/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_not_app_promotion_type/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_ru_endpoint/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_ru_endpoint/test-huaweiads-auction-response.json index dee5e9c6ebb..5c1737a381e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_ru_endpoint/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_ru_endpoint/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_with_user_geo/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_with_user_geo/test-huaweiads-auction-response.json index d6d29d2c614..760903a05d1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_with_user_geo/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_with_user_geo/test-huaweiads-auction-response.json @@ -23,7 +23,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } }, "h": 250, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_without_device_geo/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_without_device_geo/test-huaweiads-auction-response.json index d6d29d2c614..760903a05d1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_without_device_geo/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_without_device_geo/test-huaweiads-auction-response.json @@ -23,7 +23,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } }, "h": 250, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_without_userext/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_without_userext/test-huaweiads-auction-response.json index 2fcaffd7d5b..2adeb193b23 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_without_userext/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_without_userext/test-huaweiads-auction-response.json @@ -23,7 +23,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } }, "h": 300, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_wrong_mccmnc/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_wrong_mccmnc/test-huaweiads-auction-response.json index d6d29d2c614..760903a05d1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_wrong_mccmnc/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/banner_wrong_mccmnc/test-huaweiads-auction-response.json @@ -23,7 +23,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } }, "h": 250, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_include_video/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_include_video/test-huaweiads-auction-response.json index 78e93b06659..49ae58c1eee 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_include_video/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_include_video/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_single_image/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_single_image/test-huaweiads-auction-response.json index 3da566123a6..4776880e4ec 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_single_image/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_single_image/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_three_image/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_three_image/test-huaweiads-auction-response.json index 8253f6b3e62..ff14f4ba509 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_three_image/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_three_image/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_three_image_include_icon/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_three_image_include_icon/test-huaweiads-auction-response.json index b67ae7292e1..256999feb13 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_three_image_include_icon/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/native_three_image_include_icon/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/simple_video/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/simple_video/test-huaweiads-auction-response.json index 928b8e37d12..1cc40a53944 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/simple_video/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/simple_video/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/test-huaweiads-auction-response.json index c59dbe20672..75796bc960d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/test-huaweiads-auction-response.json @@ -23,7 +23,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "huaweiads" + } } }, "h": 300, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_interstitial_type/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_interstitial_type/test-huaweiads-auction-response.json index 2d7403f3e7e..2a84688584f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_interstitial_type/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_interstitial_type/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_no_icons_no_images/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_no_icons_no_images/test-huaweiads-auction-response.json index 2d7403f3e7e..2a84688584f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_no_icons_no_images/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_no_icons_no_images/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_with_icon/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_with_icon/test-huaweiads-auction-response.json index 72686361101..17d0533c6f8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_with_icon/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_with_icon/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_with_images/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_with_images/test-huaweiads-auction-response.json index 9425d23926c..c40c4f33af5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_with_images/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_rewarded_type_with_images/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_roll_type/test-huaweiads-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_roll_type/test-huaweiads-auction-response.json index 16f6247161f..5fd3eaec873 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_roll_type/test-huaweiads-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/huaweiads/video_roll_type/test-huaweiads-auction-response.json @@ -30,7 +30,10 @@ "origbidcpm": 2.8, "origbidcur": "CNY", "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "huaweiads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/iionads/test-auction-iionads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/iionads/test-auction-iionads-response.json index e37c977df53..fa138bf0b8d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/iionads/test-auction-iionads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/iionads/test-auction-iionads-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "iionads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/imds/test-auction-imds-response.json b/src/test/resources/org/prebid/server/it/openrtb2/imds/test-auction-imds-response.json index 8eae0a3d518..f5dc635bb4c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/imds/test-auction-imds-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/imds/test-auction-imds-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "imds" + } }, "origbidcpm": 7.77 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/impactify/test-auction-impactify-response.json b/src/test/resources/org/prebid/server/it/openrtb2/impactify/test-auction-impactify-response.json index 9ea7cb8766f..7ca8055396d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/impactify/test-auction-impactify-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/impactify/test-auction-impactify-response.json @@ -13,7 +13,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "impactify" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-auction-improvedigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-auction-improvedigital-response.json index a826a40c221..c9d91591fb8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-auction-improvedigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-auction-improvedigital-response.json @@ -15,7 +15,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "improvedigital" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/indicue/test-auction-indicue-response.json b/src/test/resources/org/prebid/server/it/openrtb2/indicue/test-auction-indicue-response.json index 6361cafe796..f373e228ec5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/indicue/test-auction-indicue-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/indicue/test-auction-indicue-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "indicue" + } }, "origbidcpm": 8.43 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/infytv/test-auction-infytv-response.json b/src/test/resources/org/prebid/server/it/openrtb2/infytv/test-auction-infytv-response.json index 55bd555ed6b..4b75b8e41ae 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/infytv/test-auction-infytv-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/infytv/test-auction-infytv-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "infytv" + } }, "origbidcpm": 8.43 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-auction-inmobi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-auction-inmobi-response.json index d2d1bd207fa..bc62d022ada 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-auction-inmobi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-auction-inmobi-response.json @@ -17,7 +17,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "inmobi" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/insticator/test-auction-insticator-response.json b/src/test/resources/org/prebid/server/it/openrtb2/insticator/test-auction-insticator-response.json index fa2b0a4accd..71881371150 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/insticator/test-auction-insticator-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/insticator/test-auction-insticator-response.json @@ -17,7 +17,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "insticator" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/interactiveoffers/test-auction-interactiveoffers-response.json b/src/test/resources/org/prebid/server/it/openrtb2/interactiveoffers/test-auction-interactiveoffers-response.json index 3100814d919..48554d736f8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/interactiveoffers/test-auction-interactiveoffers-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/interactiveoffers/test-auction-interactiveoffers-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "interactiveoffers" + } }, "origbidcpm": 10, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/intertech/test-auction-intertech-response.json b/src/test/resources/org/prebid/server/it/openrtb2/intertech/test-auction-intertech-response.json index 9a0fc145939..2771d04af3c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/intertech/test-auction-intertech-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/intertech/test-auction-intertech-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "intertech" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-auction-invibes-response.json b/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-auction-invibes-response.json index 4322850fa9d..da11cc5491d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-auction-invibes-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-auction-invibes-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "invibes" + } }, "origbidcpm": 1.3, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/iqx/test-auction-iqx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/iqx/test-auction-iqx-response.json index 3fc5c87e169..6bf6568f794 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/iqx/test-auction-iqx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/iqx/test-auction-iqx-response.json @@ -13,7 +13,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "iqx" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/iqzone/test-auction-iqzone-response.json b/src/test/resources/org/prebid/server/it/openrtb2/iqzone/test-auction-iqzone-response.json index b73fb55b074..f490a4e9011 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/iqzone/test-auction-iqzone-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/iqzone/test-auction-iqzone-response.json @@ -17,7 +17,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "iqzone" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json index c2c8e90c3f5..85e32f2eb24 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json @@ -12,7 +12,10 @@ "crid": "crid6", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "ix" + } }, "origbidcpm": 4.7 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/jdpmedia/test-auction-jdpmedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/jdpmedia/test-auction-jdpmedia-response.json index 31a01fdf368..9c8dff89602 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/jdpmedia/test-auction-jdpmedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/jdpmedia/test-auction-jdpmedia-response.json @@ -18,7 +18,10 @@ "mediaType": "video", "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "jdpmedia" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-response.json b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-response.json index 196ed6b59e7..603142e9877 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "jixie" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kargo/test-auction-kargo-response.json b/src/test/resources/org/prebid/server/it/openrtb2/kargo/test-auction-kargo-response.json index 2589f6a4a4d..8fc4472a83f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kargo/test-auction-kargo-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kargo/test-auction-kargo-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "kargo" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kayzen/test-auction-kayzen-response.json b/src/test/resources/org/prebid/server/it/openrtb2/kayzen/test-auction-kayzen-response.json index aaccad9be2d..e25c44a8af5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kayzen/test-auction-kayzen-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kayzen/test-auction-kayzen-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "kayzen" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-auction-kidoz-response.json b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-auction-kidoz-response.json index 5cec9fef037..621b632e05f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-auction-kidoz-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-auction-kidoz-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "kidoz" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kiviads/test-auction-kiviads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/kiviads/test-auction-kiviads-response.json index 07da2713c33..3cadec764df 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kiviads/test-auction-kiviads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kiviads/test-auction-kiviads-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "kiviads" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-auction-krushmedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-auction-krushmedia-response.json index 56f25641c69..0360f81eea1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-auction-krushmedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-auction-krushmedia-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "krushmedia" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lemmaDigital/test-auction-lemmaDigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/lemmaDigital/test-auction-lemmaDigital-response.json index 59dc0706b2d..30c8205ffdf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lemmaDigital/test-auction-lemmaDigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lemmaDigital/test-auction-lemmaDigital-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "lemmaDigital" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/liftoff/test-auction-liftoff-response.json b/src/test/resources/org/prebid/server/it/openrtb2/liftoff/test-auction-liftoff-response.json index e90d9b5f6aa..101268dc8ec 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/liftoff/test-auction-liftoff-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/liftoff/test-auction-liftoff-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "liftoff" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/limelightDigital/test-auction-limelightDigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/limelightDigital/test-auction-limelightDigital-response.json index 5bf9bad0853..43ab715d0db 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/limelightDigital/test-auction-limelightDigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/limelightDigital/test-auction-limelightDigital-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "limelightDigital" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lmkiviads/test-auction-lmkiviads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/lmkiviads/test-auction-lmkiviads-response.json index 200e13238f8..23be1717a5f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lmkiviads/test-auction-lmkiviads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lmkiviads/test-auction-lmkiviads-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "lmkiviads" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-auction-lockerdome-response.json b/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-auction-lockerdome-response.json index d1ae959bebe..c95d3501afe 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-auction-lockerdome-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-auction-lockerdome-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "lockerdome" + } }, "origbidcpm": 7.35 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/logan/test-auction-logan-response.json b/src/test/resources/org/prebid/server/it/openrtb2/logan/test-auction-logan-response.json index f5503cf319d..a16b502cf0a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/logan/test-auction-logan-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/logan/test-auction-logan-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "logan" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-auction-logicad-response.json b/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-auction-logicad-response.json index 4319787685b..4b72dbcf6aa 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-auction-logicad-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-auction-logicad-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "logicad" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/loopme/test-auction-loopme-response.json b/src/test/resources/org/prebid/server/it/openrtb2/loopme/test-auction-loopme-response.json index 30397fe4de4..fc3da869072 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/loopme/test-auction-loopme-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/loopme/test-auction-loopme-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "loopme" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/loyal/test-auction-loyal-response.json b/src/test/resources/org/prebid/server/it/openrtb2/loyal/test-auction-loyal-response.json index 58b5b47ee41..e64c7ced101 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/loyal/test-auction-loyal-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/loyal/test-auction-loyal-response.json @@ -13,7 +13,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "loyal" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-auction-lunamedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-auction-lunamedia-response.json index 194301eae99..e4a3cebc79a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-auction-lunamedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-auction-lunamedia-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "lunamedia" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mabidder/test-auction-mabidder-response.json b/src/test/resources/org/prebid/server/it/openrtb2/mabidder/test-auction-mabidder-response.json index 28e33d7e084..b22c9f2d97d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mabidder/test-auction-mabidder-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mabidder/test-auction-mabidder-response.json @@ -20,7 +20,10 @@ "origbidcpm": 3.5764000415802, "origbidcur": "CAD", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "mabidder" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/madvertise/test-auction-madvertise-response.json b/src/test/resources/org/prebid/server/it/openrtb2/madvertise/test-auction-madvertise-response.json index 1c31dddaea0..5ecd1600b55 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/madvertise/test-auction-madvertise-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/madvertise/test-auction-madvertise-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "madvertise" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/magnite/test-auction-magnite-response.json b/src/test/resources/org/prebid/server/it/openrtb2/magnite/test-auction-magnite-response.json index 111e147d710..e6c7179353c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/magnite/test-auction-magnite-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/magnite/test-auction-magnite-response.json @@ -22,7 +22,8 @@ "id1", "id2" ], - "networkId": 123 + "networkId": 123, + "adaptercode": "magnite" }, "type": "video" }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/markapp/test-auction-markapp-response.json b/src/test/resources/org/prebid/server/it/openrtb2/markapp/test-auction-markapp-response.json index a6bccc7525a..8c80a52e822 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/markapp/test-auction-markapp-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/markapp/test-auction-markapp-response.json @@ -18,7 +18,10 @@ "mediaType": "video", "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "markapp" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-auction-marsmedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-auction-marsmedia-response.json index b2536b23494..e21c8c5869f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-auction-marsmedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-auction-marsmedia-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "marsmedia" + } }, "origbidcpm": 7.35 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mediago/test-auction-mediago-response.json b/src/test/resources/org/prebid/server/it/openrtb2/mediago/test-auction-mediago-response.json index 7eb299b660f..09f2788051d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mediago/test-auction-mediago-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mediago/test-auction-mediago-response.json @@ -14,7 +14,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "mediago" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/medianet/test-auction-medianet-response.json b/src/test/resources/org/prebid/server/it/openrtb2/medianet/test-auction-medianet-response.json index 55b8dba2496..5df4d60c940 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/medianet/test-auction-medianet-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/medianet/test-auction-medianet-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "medianet" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/melozen/test-auction-melozen-response.json b/src/test/resources/org/prebid/server/it/openrtb2/melozen/test-auction-melozen-response.json index a810ba066a1..3ac02ff89bd 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/melozen/test-auction-melozen-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/melozen/test-auction-melozen-response.json @@ -13,7 +13,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "melozen" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/metax/test-auction-metax-response.json b/src/test/resources/org/prebid/server/it/openrtb2/metax/test-auction-metax-response.json index 82cc50b31be..db8a2a68ca6 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/metax/test-auction-metax-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/metax/test-auction-metax-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "metax" + } }, "origbidcpm": 1.25 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-auction-mgid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-auction-mgid-response.json index f2c474641aa..0f09db81a25 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-auction-mgid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-auction-mgid-response.json @@ -15,7 +15,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "mgid" + } }, "origbidcpm": 3.5, "crtype": "banner" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mgidx/test-auction-mgidx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/mgidx/test-auction-mgidx-response.json index d24c8274ed9..e2ff4979eb5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mgidx/test-auction-mgidx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mgidx/test-auction-mgidx-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "mgidX" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/minutemedia/test-auction-minutemedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/minutemedia/test-auction-minutemedia-response.json index 10cdbd0a6f5..3811d587bd1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/minutemedia/test-auction-minutemedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/minutemedia/test-auction-minutemedia-response.json @@ -22,7 +22,10 @@ "origbidcpm": 0.5, "origbidcur": "USD", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "minutemedia" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/missena/test-auction-missena-response.json b/src/test/resources/org/prebid/server/it/openrtb2/missena/test-auction-missena-response.json index 28f9caabf7e..344c58cb6e6 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/missena/test-auction-missena-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/missena/test-auction-missena-response.json @@ -14,7 +14,10 @@ "origbidcpm": 10.2, "origbidcur": "USD", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "missena" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-response.json b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-response.json index fb8a20ae2b0..b37259f2079 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "mobfoxpb" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-auction-mobilefuse-response.json b/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-auction-mobilefuse-response.json index 3f22980426a..57423a842ec 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-auction-mobilefuse-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-auction-mobilefuse-response.json @@ -13,7 +13,10 @@ "crid": "test_banner_crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "mobilefuse" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/motorik/test-auction-motorik-response.json b/src/test/resources/org/prebid/server/it/openrtb2/motorik/test-auction-motorik-response.json index fba432c5be4..2be376398c8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/motorik/test-auction-motorik-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/motorik/test-auction-motorik-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "motorik" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/multi_bid/test-auction-generic-genericAlias-response.json b/src/test/resources/org/prebid/server/it/openrtb2/multi_bid/test-auction-generic-genericAlias-response.json index 1e4f6f4a489..59bcbfb5eac 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/multi_bid/test-auction-generic-genericAlias-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/multi_bid/test-auction-generic-genericAlias-response.json @@ -15,6 +15,9 @@ "ext": { "prebid": { "type": "video", + "meta": { + "adaptercode": "generic" + }, "targeting": { "hb_size_generic": "300x250", "hb_cache_id": "07a81993-a3f4-4582-89c1-44a6935b192b", @@ -72,6 +75,9 @@ "ext": { "prebid": { "type": "video", + "meta": { + "adaptercode": "generic" + }, "targeting": { "hb_pb_rubN2": "8.40", "hb_uuid_rubN2": "d4f001de-4cc9-4857-9fad-70feff5c0dbc", @@ -132,6 +138,9 @@ "ext": { "prebid": { "type": "video", + "meta": { + "adaptercode": "genericAlias" + }, "targeting": { "hb_pb_genericAlias": "5.50", "hb_uuid_genericAlias": "5d7bfab8-69ea-416e-a5a1-a64db0bb218c", @@ -183,6 +192,9 @@ "ext": { "prebid": { "type": "video", + "meta": { + "adaptercode": "genericAlias" + }, "cache": { "bids": { "url": "{{ cache.resource_url }}c2da8624-f28a-4d01-bbd7-f348478c1185", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/multi_bid/test-cache-generic-genericAlias-request.json b/src/test/resources/org/prebid/server/it/openrtb2/multi_bid/test-cache-generic-genericAlias-request.json index 770ee7c9d39..618d0f9a784 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/multi_bid/test-cache-generic-genericAlias-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/multi_bid/test-cache-generic-genericAlias-request.json @@ -13,6 +13,9 @@ "ext": { "prebid": { "type": "video", + "meta": { + "adaptercode": "generic" + }, "events": { "win": "http://localhost:8080/event?t=win&b=21521324&a=5001&aid=tid&ts=1000&bidder=generic&f=i&int=", "imp": "http://localhost:8080/event?t=imp&b=21521324&a=5001&aid=tid&ts=1000&bidder=generic&f=i&int=" @@ -52,6 +55,9 @@ "ext": { "prebid": { "type": "video", + "meta": { + "adaptercode": "genericAlias" + }, "events": { "win": "http://localhost:8080/event?t=win&b=7706636740145184841&a=5001&aid=tid&ts=1000&bidder=genericAlias&f=i&int=", "imp": "http://localhost:8080/event?t=imp&b=7706636740145184841&a=5001&aid=tid&ts=1000&bidder=genericAlias&f=i&int=" @@ -85,6 +91,9 @@ "ext": { "prebid": { "type": "video", + "meta": { + "adaptercode": "generic" + }, "events": { "win": "http://localhost:8080/event?t=win&b=880290288&a=5001&aid=tid&ts=1000&bidder=generic&f=i&int=", "imp": "http://localhost:8080/event?t=imp&b=880290288&a=5001&aid=tid&ts=1000&bidder=generic&f=i&int=" @@ -124,6 +133,9 @@ "ext": { "prebid": { "type": "video", + "meta": { + "adaptercode": "genericAlias" + }, "events": { "win": "http://localhost:8080/event?t=win&b=222214214214&a=5001&aid=tid&ts=1000&bidder=genericAlias&f=i&int=", "imp": "http://localhost:8080/event?t=imp&b=222214214214&a=5001&aid=tid&ts=1000&bidder=genericAlias&f=i&int=" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/nextmillennium/test-auction-nextmillennium-response.json b/src/test/resources/org/prebid/server/it/openrtb2/nextmillennium/test-auction-nextmillennium-response.json index be5cf8b9277..a3fa75acc8c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/nextmillennium/test-auction-nextmillennium-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/nextmillennium/test-auction-nextmillennium-response.json @@ -14,7 +14,10 @@ "crid": "crid001", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "nextmillennium" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-auction-nobid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-auction-nobid-response.json index ebeea62aba0..7ec74e81f08 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-auction-nobid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-auction-nobid-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "nobid" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/oms/test-auction-oms-response.json b/src/test/resources/org/prebid/server/it/openrtb2/oms/test-auction-oms-response.json index 315114b4f75..ea09d34deff 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/oms/test-auction-oms-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/oms/test-auction-oms-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "oms" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-response.json b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-response.json index 4496bc2e4b6..5f53bca34d8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "onetag" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/openweb/test-auction-openweb-response.json b/src/test/resources/org/prebid/server/it/openrtb2/openweb/test-auction-openweb-response.json index a996e780237..e67cbb854a7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/openweb/test-auction-openweb-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/openweb/test-auction-openweb-response.json @@ -16,7 +16,10 @@ "ext": { "origbidcpm": 5.78, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "openweb" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-response.json index 0c22b5e89b9..a575e3573a2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "openx" + } }, "origbidcpm": 5.78, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/operaads/test-auction-operaads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/operaads/test-auction-operaads-response.json index 91f9dc59e5c..ae4a671ce05 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/operaads/test-auction-operaads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/operaads/test-auction-operaads-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "operaads" + } }, "origbidcpm": 3.33, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/oraki/test-auction-oraki-response.json b/src/test/resources/org/prebid/server/it/openrtb2/oraki/test-auction-oraki-response.json index 4bbd63fe482..8b55962f074 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/oraki/test-auction-oraki-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/oraki/test-auction-oraki-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "oraki" + } }, "origbidcpm": 1.25 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-auction-orbidder-response.json b/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-auction-orbidder-response.json index 40a02aff7f5..eabe3a40c94 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-auction-orbidder-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-auction-orbidder-response.json @@ -10,7 +10,10 @@ "ext": { "format": "BANNER", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "orbidder" + } }, "origbidcpm": 0.01 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-response.json b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-response.json index cb7fbc34fe8..b0d5f699b4d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "outbrain" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ownadx/test-auction-ownadx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ownadx/test-auction-ownadx-response.json index d7a74ef6d6d..da0e101f488 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ownadx/test-auction-ownadx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ownadx/test-auction-ownadx-response.json @@ -17,7 +17,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "ownadx" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-response.json index b0995267c08..d62c429d154 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "pangle" + } }, "pangle": { "adtype": 1 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pgam/test-auction-pgam-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pgam/test-auction-pgam-response.json index 82e6a8182df..9ccb517cd0b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pgam/test-auction-pgam-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pgam/test-auction-pgam-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "pgam" + } }, "origbidcpm": 8.43 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pgamssp/test-auction-pgamssp-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pgamssp/test-auction-pgamssp-response.json index 303e8a7826c..9ea4e19e8db 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pgamssp/test-auction-pgamssp-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pgamssp/test-auction-pgamssp-response.json @@ -14,7 +14,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "pgamssp" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/playdigo/test-auction-playdigo-response.json b/src/test/resources/org/prebid/server/it/openrtb2/playdigo/test-auction-playdigo-response.json index 8bfc8b3f515..a8b4e24b945 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/playdigo/test-auction-playdigo-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/playdigo/test-auction-playdigo-response.json @@ -13,7 +13,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "playdigo" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/preciso/test-auction-preciso-response.json b/src/test/resources/org/prebid/server/it/openrtb2/preciso/test-auction-preciso-response.json index c26bf519990..dc71d04d980 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/preciso/test-auction-preciso-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/preciso/test-auction-preciso-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "preciso" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json index 4df8cf0c723..964d4ea072b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json @@ -15,7 +15,10 @@ "ext": { "bidtype": 1, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "pubmatic" + } }, "origbidcpm": 4.75 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-auction-pubnative-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-auction-pubnative-response.json index d263e2b1f43..9e3188b3a0c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-auction-pubnative-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-auction-pubnative-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "pubnative" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubrise/test-auction-pubrise-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pubrise/test-auction-pubrise-response.json index 752b5519b40..56679417c40 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubrise/test-auction-pubrise-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubrise/test-auction-pubrise-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "pubrise" + } }, "origbidcpm": 1.25 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-auction-pulsepoint-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-auction-pulsepoint-response.json index 88c15aebf71..4562ed7bcbd 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-auction-pulsepoint-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-auction-pulsepoint-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "pulsepoint" + } }, "origbidcpm": 4.75 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pwbid/test-auction-pwbid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pwbid/test-auction-pwbid-response.json index b6c810ede52..0e18ccd7416 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pwbid/test-auction-pwbid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pwbid/test-auction-pwbid-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "pwbid" + } }, "origbidcpm": 8.43 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/qt/test-auction-qt-response.json b/src/test/resources/org/prebid/server/it/openrtb2/qt/test-auction-qt-response.json index 16db7e67c68..735c9327556 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/qt/test-auction-qt-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/qt/test-auction-qt-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "qt" + } }, "origbidcpm": 1.25 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/readpeak/test-auction-readpeak-response.json b/src/test/resources/org/prebid/server/it/openrtb2/readpeak/test-auction-readpeak-response.json index 06a8c3170aa..e05df94de09 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/readpeak/test-auction-readpeak-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/readpeak/test-auction-readpeak-response.json @@ -13,7 +13,9 @@ "ext": { "prebid": { "type": "banner", - "meta": {} + "meta": { + "adaptercode": "readpeak" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/relevantdigital/test-auction-relevantdigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/relevantdigital/test-auction-relevantdigital-response.json index d3531b49cca..021308ba7dc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/relevantdigital/test-auction-relevantdigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/relevantdigital/test-auction-relevantdigital-response.json @@ -15,7 +15,10 @@ "mtype": 2, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "relevantdigital" + } }, "origbidcpm": 5.78 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-request.json b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-request.json index 9ee75999128..9fffce432ec 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-request.json @@ -1,20 +1,31 @@ { - "id": "request_id", + "id": "12345", "imp": [ { - "id": "imp_id", + "id": "001", "banner": { - "w": 300, - "h": 250 + "h": 300, + "w": 250 }, "ext": { "resetdigital": { - "pubId": "lb.ads", - "zoneId": "publisherTestID" + "placement_id": "placement-id-1" } } } ], + "site": { + "domain": "https://test.com", + "page": "https://test.com/2016/06/12" + }, + "cur": [ + "USD" + ], + "device": { + "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36", + "ip": "127.0.0.1", + "language": "EN" + }, "tmax": 5000, "regs": { "ext": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-response.json index f595ea39c9f..53308c326ee 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-response.json @@ -1,24 +1,26 @@ { - "id": "request_id", + "id": "12345", "seatbid": [ { "bid": [ { - "id": "bid_id", - "impid": "imp_id", - "exp": 300, - "price": 3.33, - "adm": "adm001", - "adid": "adid001", - "cid": "cid001", - "crid": "crid001", + "adm": "test markup", + "cid": "1002088", + "crid": "1000763-1002088", + "id": "01", + "impid": "001", + "price": 1.00, "w": 300, "h": 250, + "exp": 300, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "resetdigital" + } }, - "origbidcpm": 3.33, + "origbidcpm": 1.00, "origbidcur": "USD" } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-request.json index 43d9d50841b..3b12e3d3c8a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-request.json @@ -1,57 +1,25 @@ { - "id": "request_id", - "imp": [ + "imps": [ { - "id": "imp_id", - "secure": 1, - "banner": { - "w": 300, - "h": 250 - }, - "ext": { - "tid": "${json-unit.any-string}", - "bidder": { - "pubId": "lb.ads", - "zoneId": "publisherTestID" + "bid_id": "12345", + "imp_id": "001", + "media_types": { + "banner": { + "sizes": [ + [ + 250, + 300 + ] + ] } + }, + "zone_id": { + "placementId": "placement-id-1" } } ], - "source": { - "tid": "${json-unit.any-string}" - }, "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "193.168.244.1" - }, - "at": 1, - "tmax": "${json-unit.any-number}", - "cur": [ - "USD" - ], - "regs": { - "ext": { - "gdpr": 0 - } - }, - "ext": { - "prebid": { - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - } - } + "domain": "https://test.com", + "referrer": "https://test.com/2016/06/12" } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-response.json index 631464ca55d..3397880777f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-response.json @@ -1,21 +1,16 @@ { - "id": "request_id", - "seatbid": [ + "bids": [ { - "bid": [ - { - "id": "bid_id", - "impid": "imp_id", - "price": 3.33, - "adid": "adid001", - "crid": "crid001", - "cid": "cid001", - "adm": "adm001", - "h": 250, - "w": 300 - } - ] + "bid_id": "01", + "imp_id": "001", + "cpm": 1.00, + "cid": "1002088", + "crid": "1000763-1002088", + "adid": "1002088", + "w": "300", + "h": "250", + "seat": "resetdigital", + "html": "test markup" } - ], - "cur": "USD" + ] } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-response.json b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-response.json index 4e6047c3738..f6b0d0d8a47 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "revcontent" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/richaudience/test-auction-richaudience-response.json b/src/test/resources/org/prebid/server/it/openrtb2/richaudience/test-auction-richaudience-response.json index eff55f8f91a..1e51e32b51d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/richaudience/test-auction-richaudience-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/richaudience/test-auction-richaudience-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "richaudience" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rise/test-auction-rise-response.json b/src/test/resources/org/prebid/server/it/openrtb2/rise/test-auction-rise-response.json index bd6fcb25dff..bce592cf6ad 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rise/test-auction-rise-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rise/test-auction-rise-response.json @@ -15,7 +15,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "rise" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/roulax/test-auction-roulax-response.json b/src/test/resources/org/prebid/server/it/openrtb2/roulax/test-auction-roulax-response.json index a5bbb8909ea..7055f194f31 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/roulax/test-auction-roulax-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/roulax/test-auction-roulax-response.json @@ -13,7 +13,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "roulax" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-auction-rtbhouse-response.json b/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-auction-rtbhouse-response.json index af521daf6b9..065913162d7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-auction-rtbhouse-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-auction-rtbhouse-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "rtbhouse" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-auction-rubicon-response.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-auction-rubicon-response.json index c577324825d..3baa5fddcda 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-auction-rubicon-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-auction-rubicon-response.json @@ -22,7 +22,8 @@ "id1", "id2" ], - "networkId": 123 + "networkId": 123, + "adaptercode": "rubicon" }, "type": "video" }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/salunamedia/test-auction-salunamedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/salunamedia/test-auction-salunamedia-response.json index 1ac268bddad..122a98acd88 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/salunamedia/test-auction-salunamedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/salunamedia/test-auction-salunamedia-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "sa_lunamedia" + } }, "mediaType": "banner", "origbidcpm": 3.33 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/screencore/test-auction-screencore-response.json b/src/test/resources/org/prebid/server/it/openrtb2/screencore/test-auction-screencore-response.json index b644dd7caf2..92ac3fffe4c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/screencore/test-auction-screencore-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/screencore/test-auction-screencore-response.json @@ -14,7 +14,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "screencore" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/seedingAlliance/test-auction-seedingAlliance-response.json b/src/test/resources/org/prebid/server/it/openrtb2/seedingAlliance/test-auction-seedingAlliance-response.json index b444c1eb55d..56c5476411d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/seedingAlliance/test-auction-seedingAlliance-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/seedingAlliance/test-auction-seedingAlliance-response.json @@ -14,7 +14,10 @@ "crid": "test-creative-id-1", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "seedingAlliance" + } }, "origbidcpm": 10, "origbidcur": "EUR" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-auction-sharethrough-response.json b/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-auction-sharethrough-response.json index edb951916c4..16c59d6da56 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-auction-sharethrough-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-auction-sharethrough-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "sharethrough" + } }, "origbidcpm": 0.01, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-auction-silvermob-response.json b/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-auction-silvermob-response.json index b5bbb53f45a..9e46c8d7fce 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-auction-silvermob-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-auction-silvermob-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "silvermob" + } }, "origbidcpm": 0.01, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/silverpush/test-auction-silverpush-response.json b/src/test/resources/org/prebid/server/it/openrtb2/silverpush/test-auction-silverpush-response.json index 35c5e13b170..3835f9b1adc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/silverpush/test-auction-silverpush-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/silverpush/test-auction-silverpush-response.json @@ -13,7 +13,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "silverpush" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-auction-smaato-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-auction-smaato-response.json index 463da2b0945..32dc7209653 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-auction-smaato-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-auction-smaato-response.json @@ -14,7 +14,10 @@ "exp": 300, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "smaato" + } }, "origbidcpm": 0.01, "format": "BANNER", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json index 7b143f69a40..4bb230de7f8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json @@ -19,7 +19,10 @@ "h": 576, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "smartadserver" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smarthub/test-auction-smarthub-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smarthub/test-auction-smarthub-response.json index 5121930a9be..85adc4f4103 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smarthub/test-auction-smarthub-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smarthub/test-auction-smarthub-response.json @@ -18,7 +18,10 @@ "mediaType": "video", "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "smarthub" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-auction-smartrtb-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-auction-smartrtb-response.json index 0797e39c9a7..2ff787b7c55 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-auction-smartrtb-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-auction-smartrtb-response.json @@ -10,7 +10,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "smartrtb" + } }, "origbidcpm": 0.01 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartx/test-auction-smartx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smartx/test-auction-smartx-response.json index 0e92d0f7a89..9746b66b080 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartx/test-auction-smartx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartx/test-auction-smartx-response.json @@ -14,7 +14,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "smartx" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-response.json index 0b6d4de8672..d62bae570f7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-response.json @@ -13,7 +13,10 @@ "crid": "crid", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "smartyads" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smilewanted/test-auction-smilewanted-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smilewanted/test-auction-smilewanted-response.json index c7e19cf69cf..b32e54468eb 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smilewanted/test-auction-smilewanted-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smilewanted/test-auction-smilewanted-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "smilewanted" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smrtconnect/test-auction-smrtconnect-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smrtconnect/test-auction-smrtconnect-response.json index d3c9f4e8a2d..ef4f6b493ac 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smrtconnect/test-auction-smrtconnect-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smrtconnect/test-auction-smrtconnect-response.json @@ -17,7 +17,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "smrtconnect" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-auction-sonobi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-auction-sonobi-response.json index 59208dd177e..60dc8cb5f31 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-auction-sonobi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-auction-sonobi-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "sonobi" + } }, "origbidcpm": 1.25, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-auction-sovrn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-auction-sovrn-response.json index 58d1bef9d8d..70c6e55cd08 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-auction-sovrn-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-auction-sovrn-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "sovrn" + } }, "origbidcpm": 5.78 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sovrnxsp/test-auction-sovrnxsp-response.json b/src/test/resources/org/prebid/server/it/openrtb2/sovrnxsp/test-auction-sovrnxsp-response.json index 3d0373bdb97..3aa06b3a2b1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sovrnxsp/test-auction-sovrnxsp-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sovrnxsp/test-auction-sovrnxsp-response.json @@ -16,7 +16,10 @@ "ext": { "creative_type": 1, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "sovrnXsp" + } }, "origbidcpm": 5.78 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sspbc/test-auction-sspbc-response.json b/src/test/resources/org/prebid/server/it/openrtb2/sspbc/test-auction-sspbc-response.json index 8e87bb83efd..fd673b34ff5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sspbc/test-auction-sspbc-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sspbc/test-auction-sspbc-response.json @@ -21,7 +21,10 @@ "slotid": "005", "tagid": "slot", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "sspbc" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-auction-response.json index f25cdd92a2f..0e09537a4c7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-auction-response.json @@ -15,6 +15,9 @@ "ext": { "prebid": { "type": "banner", + "meta": { + "adaptercode": "generic" + }, "targeting": { "hb_size_generic": "300x250", "hb_cache_id": "474175c2-815f-4bde-90ad-935d2f6e1aa0", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-cache-request.json b/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-cache-request.json index ba1f6a2d32c..369d162359a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-cache-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-cache-request.json @@ -12,7 +12,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "generic" + } }, "origbidcpm": 0.8 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/streamlyn/test-auction-streamlyn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/streamlyn/test-auction-streamlyn-response.json index 919e3fcdcb6..65df62c2c58 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/streamlyn/test-auction-streamlyn-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/streamlyn/test-auction-streamlyn-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "streamlyn" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/stroeercore/test-auction-stroeercore-response.json b/src/test/resources/org/prebid/server/it/openrtb2/stroeercore/test-auction-stroeercore-response.json index c27cc4c6474..aab841a83de 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/stroeercore/test-auction-stroeercore-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/stroeercore/test-auction-stroeercore-response.json @@ -16,7 +16,10 @@ "origbidcpm": 6.77, "origbidcur": "EUR", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "stroeerCore" + } } } }, @@ -31,7 +34,10 @@ "origbidcpm": 5.7, "origbidcur": "EUR", "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "stroeerCore" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/suntContent/test-auction-suntContent-response.json b/src/test/resources/org/prebid/server/it/openrtb2/suntContent/test-auction-suntContent-response.json index 7977110e93b..eb1dbb4ffc9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/suntContent/test-auction-suntContent-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/suntContent/test-auction-suntContent-response.json @@ -14,7 +14,10 @@ "crid": "test-creative-id-1", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "suntContent" + } }, "origbidcpm": 10, "origbidcur": "EUR" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/taboola/test-auction-taboola-response.json b/src/test/resources/org/prebid/server/it/openrtb2/taboola/test-auction-taboola-response.json index ba87a68d153..a90d55133e1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/taboola/test-auction-taboola-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/taboola/test-auction-taboola-response.json @@ -15,7 +15,10 @@ "ext": { "origbidcpm": 8.43, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "taboola" + } } } }, @@ -31,7 +34,10 @@ "ext": { "origbidcpm": 8.43, "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "taboola" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-auction-tappx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-auction-tappx-response.json index 1fe9c183839..18479e94b80 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-auction-tappx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-auction-tappx-response.json @@ -22,7 +22,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "tappx" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/teads/test-auction-teads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/teads/test-auction-teads-response.json index 37411e7dfb1..79678687307 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/teads/test-auction-teads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/teads/test-auction-teads-response.json @@ -25,7 +25,8 @@ "type": "banner", "meta": { "rendererName": "teads", - "rendererVersion": "5.0.25" + "rendererVersion": "5.0.25", + "adaptercode": "teads" } }, "origbidcpm": 33 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-auction-telaria-response.json b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-auction-telaria-response.json index a25794e3d5d..a62c605a690 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-auction-telaria-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-auction-telaria-response.json @@ -13,7 +13,10 @@ "exp": 120, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "telaria" + } }, "origbidcpm": 0.01, "format": "VIDEO" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tgm/test-auction-tgm-response.json b/src/test/resources/org/prebid/server/it/openrtb2/tgm/test-auction-tgm-response.json index 7630f73ad2a..17361a0bdb4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tgm/test-auction-tgm-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tgm/test-auction-tgm-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "tgm" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/theadx/test-auction-theadx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/theadx/test-auction-theadx-response.json index 023554088ff..a01054542d7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/theadx/test-auction-theadx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/theadx/test-auction-theadx-response.json @@ -12,7 +12,10 @@ "crid": "crid6", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "theadx" + } }, "origbidcpm": 4.7 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/thetradedesk/test-auction-thetradedesk-response.json b/src/test/resources/org/prebid/server/it/openrtb2/thetradedesk/test-auction-thetradedesk-response.json index 1bc78519e0b..e3fe5f37e65 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/thetradedesk/test-auction-thetradedesk-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/thetradedesk/test-auction-thetradedesk-response.json @@ -14,7 +14,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "thetradedesk" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/thirtythreeacross/test-auction-thirtythreeacross-response.json b/src/test/resources/org/prebid/server/it/openrtb2/thirtythreeacross/test-auction-thirtythreeacross-response.json index e83af540d6d..1013a518a70 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/thirtythreeacross/test-auction-thirtythreeacross-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/thirtythreeacross/test-auction-thirtythreeacross-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "thirtythreeacross" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tpmn/test-auction-tpmn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/tpmn/test-auction-tpmn-response.json index 96eba6c8ffc..8075c1dcf84 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tpmn/test-auction-tpmn-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tpmn/test-auction-tpmn-response.json @@ -13,7 +13,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "tpmn" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tradplus/test-auction-tradplus-response.json b/src/test/resources/org/prebid/server/it/openrtb2/tradplus/test-auction-tradplus-response.json index cf2087e1fab..affccd3fcdf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tradplus/test-auction-tradplus-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tradplus/test-auction-tradplus-response.json @@ -17,7 +17,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "tradplus" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/trafficgate/test-auction-trafficgate-response.json b/src/test/resources/org/prebid/server/it/openrtb2/trafficgate/test-auction-trafficgate-response.json index d6161b71c26..9d6ee41808e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/trafficgate/test-auction-trafficgate-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/trafficgate/test-auction-trafficgate-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "trafficgate" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tredio/test-auction-tredio-response.json b/src/test/resources/org/prebid/server/it/openrtb2/tredio/test-auction-tredio-response.json index 8bfb5d60490..2cbb636a34c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tredio/test-auction-tredio-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tredio/test-auction-tredio-response.json @@ -18,7 +18,10 @@ "mediaType": "video", "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "tredio" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-auction-triplelift-response.json b/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-auction-triplelift-response.json index db4cc84b585..3a2447d9657 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-auction-triplelift-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-auction-triplelift-response.json @@ -20,7 +20,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "triplelift" + } }, "origbidcpm": 0.5, "origbidcur": "USD", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-response.json b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-response.json index e1b8d7476fa..7c6a3dd8f39 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-response.json @@ -20,7 +20,10 @@ "w": 300, "ext": { "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "triplelift_native" + } }, "origbidcpm": 0.5, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/trustedstack/test-auction-trustedstack-response.json b/src/test/resources/org/prebid/server/it/openrtb2/trustedstack/test-auction-trustedstack-response.json index d9c328fcd58..2591b3962f0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/trustedstack/test-auction-trustedstack-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/trustedstack/test-auction-trustedstack-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "trustedstack" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-response.json index e8c5b12f12d..2beebab027e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "ttx" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-auction-ucfunnel-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-auction-ucfunnel-response.json index 6fa5ba63fb0..ea1a7cf8684 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-auction-ucfunnel-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-auction-ucfunnel-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "ucfunnel" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/undertone/test-auction-undertone-response.json b/src/test/resources/org/prebid/server/it/openrtb2/undertone/test-auction-undertone-response.json index 2d3ab23f164..46e401ac9e8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/undertone/test-auction-undertone-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/undertone/test-auction-undertone-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "undertone" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-response.json index 1e5d00d5b89..c989c1f58fe 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "unicorn" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-auction-unruly-response.json b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-auction-unruly-response.json index 94153ee8cdc..a8a5561e567 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-auction-unruly-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-auction-unruly-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "unruly" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/vidazoo/test-auction-vidazoo-response.json b/src/test/resources/org/prebid/server/it/openrtb2/vidazoo/test-auction-vidazoo-response.json index 57c24081c54..d1c667b4127 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/vidazoo/test-auction-vidazoo-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/vidazoo/test-auction-vidazoo-response.json @@ -14,7 +14,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "vidazoo" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/videobyte/test-auction-videobyte-response.json b/src/test/resources/org/prebid/server/it/openrtb2/videobyte/test-auction-videobyte-response.json index 705f5bf376b..61e235ccdba 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/videobyte/test-auction-videobyte-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/videobyte/test-auction-videobyte-response.json @@ -18,7 +18,10 @@ "origbidcpm": 3.33, "origbidcur": "USD", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "videobyte" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/videoheroes/test-auction-videoheroes-response.json b/src/test/resources/org/prebid/server/it/openrtb2/videoheroes/test-auction-videoheroes-response.json index 4b345c3aef3..7bcb0989798 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/videoheroes/test-auction-videoheroes-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/videoheroes/test-auction-videoheroes-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "videoheroes" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/vidoomy/test-auction-vidoomy-response.json b/src/test/resources/org/prebid/server/it/openrtb2/vidoomy/test-auction-vidoomy-response.json index 45012edd4c0..65e53d320ab 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/vidoomy/test-auction-vidoomy-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/vidoomy/test-auction-vidoomy-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "vidoomy" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/vimayx/test-auction-vimayx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/vimayx/test-auction-vimayx-response.json index 0e17226a62c..218b16cda60 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/vimayx/test-auction-vimayx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/vimayx/test-auction-vimayx-response.json @@ -18,7 +18,10 @@ "mediaType": "video", "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "vimayx" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/visiblemeasures/test-auction-visiblemeasures-response.json b/src/test/resources/org/prebid/server/it/openrtb2/visiblemeasures/test-auction-visiblemeasures-response.json index 141b8f5959a..57c0b534e34 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/visiblemeasures/test-auction-visiblemeasures-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/visiblemeasures/test-auction-visiblemeasures-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "visiblemeasures" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/visx/test-auction-visx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/visx/test-auction-visx-response.json index 6f9563edecd..3982971cb7f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/visx/test-auction-visx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/visx/test-auction-visx-response.json @@ -17,7 +17,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "visx" + } }, "origbidcpm": 0.5 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/vox/test-auction-vox-response.json b/src/test/resources/org/prebid/server/it/openrtb2/vox/test-auction-vox-response.json index b7dfff7b29f..6416b1a430f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/vox/test-auction-vox-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/vox/test-auction-vox-response.json @@ -15,7 +15,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "vox" + } }, "origbidcpm": 3.1415, "origbidcur": "USD" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-auction-vrtcal-response.json b/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-auction-vrtcal-response.json index 554ace08a73..85fb5ab85cc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-auction-vrtcal-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-auction-vrtcal-response.json @@ -15,7 +15,10 @@ "mtype": 1, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "vrtcal" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/vungle/test-auction-vungle-response.json b/src/test/resources/org/prebid/server/it/openrtb2/vungle/test-auction-vungle-response.json index 2226f9e6b7f..9b3dae5a329 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/vungle/test-auction-vungle-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/vungle/test-auction-vungle-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "vungle" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/xeworks/test-auction-xeworks-response.json b/src/test/resources/org/prebid/server/it/openrtb2/xeworks/test-auction-xeworks-response.json index b3ece494e63..f0f18f26c37 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/xeworks/test-auction-xeworks-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/xeworks/test-auction-xeworks-response.json @@ -14,7 +14,10 @@ "crid": "test-creative-id-1", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "xeworks" + } }, "origbidcpm": 10, "origbidcur": "EUR" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/xtrmqb/test-auction-xtrmqb-response.json b/src/test/resources/org/prebid/server/it/openrtb2/xtrmqb/test-auction-xtrmqb-response.json index 961f3c98437..582e82578f8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/xtrmqb/test-auction-xtrmqb-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/xtrmqb/test-auction-xtrmqb-response.json @@ -12,7 +12,10 @@ "ext": { "origbidcpm": 3.33, "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "xtrmqb" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yahooads/test-auction-yahooads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yahooads/test-auction-yahooads-response.json index 2ef360e66b4..c91a58fa074 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yahooads/test-auction-yahooads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yahooads/test-auction-yahooads-response.json @@ -14,7 +14,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "yahooAds" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yandex/test-auction-yandex-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yandex/test-auction-yandex-response.json index 50db4b9296f..e08cecc8bb3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yandex/test-auction-yandex-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yandex/test-auction-yandex-response.json @@ -14,7 +14,10 @@ "h": 600, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "yandex" + } }, "origbidcpm": 1.25 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-auction-yeahmobi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-auction-yeahmobi-response.json index 4bc553b800e..b89a2e90580 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-auction-yeahmobi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-auction-yeahmobi-response.json @@ -13,7 +13,10 @@ "crid": "1", "ext": { "prebid": { - "type": "native" + "type": "native", + "meta": { + "adaptercode": "yeahmobi" + } }, "origbidcpm": 1.2 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yearxero/test-auction-yearxero-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yearxero/test-auction-yearxero-response.json index f17d2e27d7d..ed08050f4cf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yearxero/test-auction-yearxero-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yearxero/test-auction-yearxero-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "yearxero" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-auction-yieldlab-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-auction-yieldlab-response.json index 52e84781542..bb940fbcddd 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-auction-yieldlab-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-auction-yieldlab-response.json @@ -17,7 +17,10 @@ "origbidcpm": 2.01, "origbidcur": "EUR", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "yieldlab" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-auction-yieldmo-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-auction-yieldmo-response.json index 7971beb1204..4c4c4658f46 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-auction-yieldmo-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-auction-yieldmo-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "yieldmo" + } }, "origbidcpm": 3.33, "mediatype": "banner" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-auction-yieldone-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-auction-yieldone-response.json index e2bca209c2c..040ca8b8f94 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-auction-yieldone-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-auction-yieldone-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "yieldone" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-response.json b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-response.json index 3fc40dda751..277d2322d4d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "zeroclickfraud" + } }, "origbidcpm": 7.77 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/zeta_global_ssp/test-auction-zeta_global_ssp-response.json b/src/test/resources/org/prebid/server/it/openrtb2/zeta_global_ssp/test-auction-zeta_global_ssp-response.json index e1de127c348..5de8569c298 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/zeta_global_ssp/test-auction-zeta_global_ssp-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/zeta_global_ssp/test-auction-zeta_global_ssp-response.json @@ -16,7 +16,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "zeta_global_ssp" + } }, "origbidcpm": 3.33 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/zmaticoo/test-auction-zmaticoo-response.json b/src/test/resources/org/prebid/server/it/openrtb2/zmaticoo/test-auction-zmaticoo-response.json index ab36fa541e6..aaa264babf4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/zmaticoo/test-auction-zmaticoo-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/zmaticoo/test-auction-zmaticoo-response.json @@ -17,7 +17,10 @@ "h": 250, "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "zmaticoo" + } }, "origbidcpm": 3.33 } From d800ede776b072c4df1a9f34cd2b641e4b8ef168 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Mon, 3 Mar 2025 11:18:22 +0100 Subject: [PATCH 02/23] Multiple Bidder Codes --- .../prebid/server/auction/BidsAdjuster.java | 16 +- .../server/auction/ExchangeService.java | 19 +- .../openrtb/ext/request/ExtRequestPrebid.java | 3 + .../ExtRequestPrebidAlternateBidderCodes.java | 15 ++ ...uestPrebidAlternateBidderCodesBidder.java} | 4 +- .../prebid/server/settings/model/Account.java | 3 +- .../model/AccountAlternateBidderCodes.java | 15 -- .../validation/ResponseBidValidator.java | 32 +-- .../server/auction/BidsAdjusterTest.java | 18 +- .../server/auction/ExchangeServiceTest.java | 65 +++++- .../validation/ResponseBidValidatorTest.java | 195 ++++++++++-------- 11 files changed, 254 insertions(+), 131 deletions(-) create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodes.java rename src/main/java/org/prebid/server/{settings/model/AccountAlternateBidderCodesBidder.java => proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java} (69%) delete mode 100644 src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java diff --git a/src/main/java/org/prebid/server/auction/BidsAdjuster.java b/src/main/java/org/prebid/server/auction/BidsAdjuster.java index 4ae7a6e3e3e..ffcf748af4f 100644 --- a/src/main/java/org/prebid/server/auction/BidsAdjuster.java +++ b/src/main/java/org/prebid/server/auction/BidsAdjuster.java @@ -10,6 +10,7 @@ import org.prebid.server.bidder.model.BidderError; import org.prebid.server.bidder.model.BidderSeatBid; import org.prebid.server.floors.PriceFloorEnforcer; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; import org.prebid.server.util.ObjectUtil; import org.prebid.server.validation.ResponseBidValidator; import org.prebid.server.validation.model.ValidationResult; @@ -40,10 +41,15 @@ public BidsAdjuster(ResponseBidValidator responseBidValidator, public List validateAndAdjustBids(List auctionParticipations, AuctionContext auctionContext, - BidderAliases aliases) { + BidderAliases aliases, + ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { return auctionParticipations.stream() - .map(auctionParticipation -> validBidderResponse(auctionParticipation, auctionContext, aliases)) + .map(auctionParticipation -> validBidderResponse( + auctionParticipation, + auctionContext, + aliases, + alternateBidderCodes)) .map(auctionParticipation -> bidAdjustmentsProcessor.enrichWithAdjustedBids( auctionParticipation, @@ -65,7 +71,8 @@ public List validateAndAdjustBids(List runAuction(AuctionContext receivedContext) { final Map bidderToMultiBid = bidderToMultiBids(bidRequest, debugWarnings); receivedContext.getBidRejectionTrackers().putAll(makeBidRejectionTrackers(bidRequest, aliases)); + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = getAlternateBidderCodes(bidRequest, account); + final boolean debugEnabled = receivedContext.getDebugContext().isDebugEnabled(); metrics.updateDebugRequestMetrics(debugEnabled); metrics.updateAccountDebugRequestMetrics(account, debugEnabled); @@ -275,8 +278,11 @@ private Future runAuction(AuctionContext receivedContext) { context.getBidRejectionTrackers())) .map(auctionParticipations -> dropZeroNonDealBids( auctionParticipations, debugWarnings, debugEnabled)) - .map(auctionParticipations -> - bidsAdjuster.validateAndAdjustBids(auctionParticipations, context, aliases)) + .map(auctionParticipations -> bidsAdjuster.validateAndAdjustBids( + auctionParticipations, + context, + aliases, + alternateBidderCodes)) .map(auctionParticipations -> updateResponsesMetrics(auctionParticipations, account, aliases)) .map(context::with)) // produce response from bidder results @@ -298,6 +304,15 @@ private BidderAliases aliases(BidRequest bidRequest) { return BidderAliases.of(aliases, aliasgvlids, bidderCatalog); } + private static ExtRequestPrebidAlternateBidderCodes getAlternateBidderCodes(BidRequest bidRequest, + Account account) { + + return Optional.ofNullable(bidRequest.getExt()) + .map(ExtRequest::getPrebid) + .map(ExtRequestPrebid::getAlternateBidderCodes) + .orElse(account.getAlternateBidderCodes()); + } + private static ExtRequestTargeting targeting(BidRequest bidRequest) { final ExtRequestPrebid prebid = PbsUtil.extRequestPrebid(bidRequest); return prebid != null ? prebid.getTargeting() : null; diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java index 33b326b2638..0667ac571c7 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java @@ -190,4 +190,7 @@ public class ExtRequestPrebid { */ @JsonProperty("paaformat") PaaFormat paaFormat; + + @JsonProperty("alternatebidderscodes") + ExtRequestPrebidAlternateBidderCodes alternateBidderCodes; } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodes.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodes.java new file mode 100644 index 00000000000..578d5402f8b --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodes.java @@ -0,0 +1,15 @@ +package org.prebid.server.proto.openrtb.ext.request; + +import lombok.Builder; +import lombok.Value; + +import java.util.Map; + +@Builder(toBuilder = true) +@Value +public class ExtRequestPrebidAlternateBidderCodes { + + Boolean enabled; + + Map bidders; +} diff --git a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java similarity index 69% rename from src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java rename to src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java index dea69c17da1..d51d9dd8651 100644 --- a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java @@ -1,4 +1,4 @@ -package org.prebid.server.settings.model; +package org.prebid.server.proto.openrtb.ext.request; import com.fasterxml.jackson.annotation.JsonAlias; import lombok.Builder; @@ -8,7 +8,7 @@ @Builder(toBuilder = true) @Value -public class AccountAlternateBidderCodesBidder { +public class ExtRequestPrebidAlternateBidderCodesBidder { Boolean enabled; diff --git a/src/main/java/org/prebid/server/settings/model/Account.java b/src/main/java/org/prebid/server/settings/model/Account.java index 3224b0e7a48..5a937b4ebed 100644 --- a/src/main/java/org/prebid/server/settings/model/Account.java +++ b/src/main/java/org/prebid/server/settings/model/Account.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonAlias; import lombok.Builder; import lombok.Value; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; @Builder(toBuilder = true) @Value @@ -28,7 +29,7 @@ public class Account { AccountSettings settings; @JsonAlias("alternatebiddercodes") - AccountAlternateBidderCodes alternateBidderCodes; + ExtRequestPrebidAlternateBidderCodes alternateBidderCodes; public static Account empty(String id) { return Account.builder().id(id).build(); diff --git a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java deleted file mode 100644 index ffbebc0d5c6..00000000000 --- a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.settings.model; - -import lombok.Builder; -import lombok.Value; - -import java.util.Map; - -@Builder(toBuilder = true) -@Value -public class AccountAlternateBidderCodes { - - Boolean enabled; - - Map bidders; -} diff --git a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java index 585175a9a82..bd3ca70f42b 100644 --- a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java +++ b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java @@ -22,8 +22,8 @@ import org.prebid.server.metric.Metrics; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.settings.model.Account; -import org.prebid.server.settings.model.AccountAlternateBidderCodes; -import org.prebid.server.settings.model.AccountAlternateBidderCodesBidder; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodesBidder; import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.settings.model.AccountBidValidationConfig; import org.prebid.server.settings.model.BidValidationEnforcement; @@ -82,7 +82,8 @@ public ResponseBidValidator(BidValidationEnforcement bannerMaxSizeEnforcement, public ValidationResult validate(BidderBid bidderBid, String bidder, AuctionContext auctionContext, - BidderAliases aliases) { + BidderAliases aliases, + ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { final Bid bid = bidderBid.getBid(); final BidRequest bidRequest = auctionContext.getBidRequest(); @@ -94,7 +95,7 @@ public ValidationResult validate(BidderBid bidderBid, validateCommonFields(bid); validateTypeSpecific(bidderBid, bidder); validateCurrency(bidderBid.getBidCurrency()); - validateSeat(bidderBid, bidder, account, bidRejectionTracker, warnings); + validateSeat(bidderBid, bidder, account, bidRejectionTracker, alternateBidderCodes, warnings); final Imp correspondingImp = findCorrespondingImp(bid, bidRequest); if (bidderBid.getType() == BidType.banner) { @@ -166,14 +167,18 @@ private void validateSeat(BidderBid bid, String bidder, Account account, BidRejectionTracker bidRejectionTracker, + ExtRequestPrebidAlternateBidderCodes alternateBidderCodes, List warnings) { if (bid.getSeat() == null || StringUtils.equals(bid.getSeat(), bidder)) { return; } - final AccountAlternateBidderCodesBidder alternateBidder = resolveAlternateBidder(bidder, account); - if (!isAlternateBidderCodesEnabled(account) || alternateBidder == null) { + final ExtRequestPrebidAlternateBidderCodesBidder alternateBidder = resolveAlternateBidder( + bidder, + alternateBidderCodes); + + if (!isAlternateBidderCodesEnabled(alternateBidderCodes) || alternateBidder == null) { warnings.add(rejectBidOnInvalidSeat(bid, bidder, account, bidRejectionTracker)); return; } @@ -188,15 +193,18 @@ private void validateSeat(BidderBid bid, } } - private static Boolean isAlternateBidderCodesEnabled(Account account) { - return Optional.ofNullable(account.getAlternateBidderCodes()) - .map(AccountAlternateBidderCodes::getEnabled) + private static Boolean isAlternateBidderCodesEnabled(ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { + return Optional.ofNullable(alternateBidderCodes) + .map(ExtRequestPrebidAlternateBidderCodes::getEnabled) .orElse(false); } - private static AccountAlternateBidderCodesBidder resolveAlternateBidder(String bidder, Account account) { - return Optional.ofNullable(account.getAlternateBidderCodes()) - .map(AccountAlternateBidderCodes::getBidders) + private static ExtRequestPrebidAlternateBidderCodesBidder resolveAlternateBidder( + String bidder, + ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { + + return Optional.ofNullable(alternateBidderCodes) + .map(ExtRequestPrebidAlternateBidderCodes::getBidders) .map(bidders -> bidders.get(bidder)) .filter(alternate -> BooleanUtils.isTrue(alternate.getEnabled())) .orElse(null); diff --git a/src/test/java/org/prebid/server/auction/BidsAdjusterTest.java b/src/test/java/org/prebid/server/auction/BidsAdjusterTest.java index 9bfbc9cb143..927cf297b44 100644 --- a/src/test/java/org/prebid/server/auction/BidsAdjusterTest.java +++ b/src/test/java/org/prebid/server/auction/BidsAdjusterTest.java @@ -61,7 +61,7 @@ public class BidsAdjusterTest extends VertxTest { @BeforeEach public void setUp() { - given(responseBidValidator.validate(any(), any(), any(), any())).willReturn(ValidationResult.success()); + given(responseBidValidator.validate(any(), any(), any(), any(), any())).willReturn(ValidationResult.success()); given(priceFloorEnforcer.enforce(any(), any(), any(), any())).willAnswer(inv -> inv.getArgument(1)); given(dsaEnforcer.enforce(any(), any(), any())).willAnswer(inv -> inv.getArgument(1)); @@ -100,7 +100,7 @@ public void shouldReturnBidsAdjustedByBidAdjustmentsProcessor() { // when final List result = target.validateAndAdjustBids( - auctionParticipations, auctionContext, null); + auctionParticipations, auctionContext, null, null); // then assertThat(result) @@ -142,7 +142,7 @@ public void shouldReturnBidsAcceptedByPriceFloorEnforcer() { // when final List result = target.validateAndAdjustBids( - auctionParticipations, auctionContext, null); + auctionParticipations, auctionContext, null, null); // then assertThat(result) @@ -185,7 +185,7 @@ public void shouldReturnBidsAcceptedByDsaEnforcer() { // when final List result = target - .validateAndAdjustBids(auctionParticipations, auctionContext, null); + .validateAndAdjustBids(auctionParticipations, auctionContext, null, null); // then assertThat(result) @@ -213,7 +213,7 @@ public void shouldTolerateResponseBidValidationErrors() { .auctiontimestamp(1000L) .build()))); - when(responseBidValidator.validate(any(), any(), any(), any())) + when(responseBidValidator.validate(any(), any(), any(), any(), any())) .thenReturn(ValidationResult.error("Error: bid validation error.")); final List auctionParticipations = givenAuctionParticipation(bidderResponse, bidRequest); @@ -221,7 +221,7 @@ public void shouldTolerateResponseBidValidationErrors() { // when final List result = target - .validateAndAdjustBids(auctionParticipations, auctionContext, null); + .validateAndAdjustBids(auctionParticipations, auctionContext, null, null); // then assertThat(result) @@ -256,7 +256,7 @@ public void shouldTolerateResponseBidValidationWarnings() { .auctiontimestamp(1000L) .build()))); - when(responseBidValidator.validate(any(), any(), any(), any())) + when(responseBidValidator.validate(any(), any(), any(), any(), any())) .thenReturn(ValidationResult.warning(singletonList("Error: bid validation warning."))); final List auctionParticipations = givenAuctionParticipation(bidderResponse, bidRequest); @@ -264,7 +264,7 @@ public void shouldTolerateResponseBidValidationWarnings() { // when final List result = target - .validateAndAdjustBids(auctionParticipations, auctionContext, null); + .validateAndAdjustBids(auctionParticipations, auctionContext, null, null); // then assertThat(result) @@ -301,7 +301,7 @@ public void shouldAddWarningAboutMultipleCurrency() { // when final List result = target - .validateAndAdjustBids(auctionParticipations, auctionContext, null); + .validateAndAdjustBids(auctionParticipations, auctionContext, null, null); // then assertThat(result).hasSize(1); diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index 8ea7f336e31..014390c61f5 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -111,6 +111,7 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestCurrency; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidBidderConfig; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCache; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCacheBids; @@ -351,7 +352,7 @@ public void setUp() { false, AuctionResponsePayloadImpl.of(invocation.getArgument(0))))); - given(bidsAdjuster.validateAndAdjustBids(any(), any(), any())) + given(bidsAdjuster.validateAndAdjustBids(any(), any(), any(), any())) .willAnswer(invocation -> invocation.getArgument(0)); given(mediaTypeProcessor.process(any(), anyString(), any(), any())) @@ -3062,6 +3063,68 @@ public void shouldIncrementCommonMetrics() { eq("someBidder"), any(), eq(10000L), eq(false), eq("banner")); } + @Test + public void shouldValidateBidsWithExtRequestPrebidAlternateBidderCodes() { + // given + given(httpBidderRequester.requestBids(any(), any(), any(), any(), any(), any(), anyBoolean())) + .willReturn(Future.succeededFuture(givenSeatBid(singletonList( + givenBidderBid(Bid.builder().impid("impId").price(TEN).build()))))); + + final ExtRequestPrebidAlternateBidderCodes requestAlternateBidderCodes = + ExtRequestPrebidAlternateBidderCodes.builder().enabled(false).build(); + + final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1)), + builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .alternateBidderCodes(requestAlternateBidderCodes) + .build()))); + + final ExtRequestPrebidAlternateBidderCodes accountAlternateBidderCodes = + ExtRequestPrebidAlternateBidderCodes.builder().enabled(true).build(); + + final Account givenAccount = Account.builder() + .id("accountId") + .auction(AccountAuctionConfig.builder() + .events(AccountEventsConfig.of(true)) + .build()) + .alternateBidderCodes(accountAlternateBidderCodes) + .build(); + + // when + target.holdAuction(givenRequestContext(bidRequest, givenAccount)); + + // then + verify(bidsAdjuster).validateAndAdjustBids(any(), any(), any(), eq(requestAlternateBidderCodes)); + } + + @Test + public void shouldValidateBidsWithAccountAlternateBidderCodesWhenRequestOnesAreAbsent() { + // given + given(httpBidderRequester.requestBids(any(), any(), any(), any(), any(), any(), anyBoolean())) + .willReturn(Future.succeededFuture(givenSeatBid(singletonList( + givenBidderBid(Bid.builder().impid("impId").price(TEN).build()))))); + + final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1)), + builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder().build()))); + + final ExtRequestPrebidAlternateBidderCodes accountAlternateBidderCodes = + ExtRequestPrebidAlternateBidderCodes.builder().enabled(true).build(); + + final Account givenAccount = Account.builder() + .id("accountId") + .auction(AccountAuctionConfig.builder() + .events(AccountEventsConfig.of(true)) + .build()) + .alternateBidderCodes(accountAlternateBidderCodes) + .build(); + + // when + target.holdAuction(givenRequestContext(bidRequest, givenAccount)); + + // then + verify(bidsAdjuster).validateAndAdjustBids(any(), any(), any(), eq(accountAlternateBidderCodes)); + } + @Test public void shouldCallUpdateCookieMetricsWithExpectedValue() { // given diff --git a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java index 943a3fdbc42..265f4331da5 100644 --- a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java @@ -19,10 +19,10 @@ import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodesBidder; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.settings.model.Account; -import org.prebid.server.settings.model.AccountAlternateBidderCodes; -import org.prebid.server.settings.model.AccountAlternateBidderCodesBidder; import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.settings.model.AccountBidValidationConfig; import org.prebid.server.validation.model.ValidationResult; @@ -77,7 +77,8 @@ public void validateShouldFailedIfBidderBidCurrencyIsIncorrect() { givenBid(BidType.banner, "invalid", identity()), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.getErrors()).containsOnly("BidResponse currency \"invalid\" is not valid"); @@ -88,7 +89,11 @@ public void validateShouldFailedIfBidderBidCurrencyIsIncorrect() { public void validateShouldFailIfMissingBid() { // when final ValidationResult result = target.validate( - BidderBid.of(null, null, "USD"), BIDDER_NAME, givenAuctionContext(), bidderAliases); + BidderBid.of(null, null, "USD"), + BIDDER_NAME, + givenAuctionContext(), + bidderAliases, + null); // then assertThat(result.getErrors()).containsOnly("Empty bid object submitted"); @@ -99,7 +104,7 @@ public void validateShouldFailIfMissingBid() { public void validateShouldFailIfBidHasNoId() { // when final ValidationResult result = target.validate( - givenBid(builder -> builder.id(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases); + givenBid(builder -> builder.id(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases, null); // then assertThat(result.getErrors()).containsOnly("Bid missing required field 'id'"); @@ -110,7 +115,7 @@ public void validateShouldFailIfBidHasNoId() { public void validateShouldFailIfBidHasNoImpId() { // when final ValidationResult result = target.validate( - givenBid(builder -> builder.impid(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases); + givenBid(builder -> builder.impid(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases, null); // then assertThat(result.getErrors()).containsOnly("Bid \"bidId1\" missing required field 'impid'"); @@ -124,7 +129,8 @@ public void validateShouldSuccessForDealZeroPriceBid() { givenVideoBid(builder -> builder.price(BigDecimal.valueOf(0)).dealid("dealId")), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.hasErrors()).isFalse(); @@ -135,7 +141,7 @@ public void validateShouldSuccessForDealZeroPriceBid() { public void validateShouldFailIfBidHasNoCrid() { // when final ValidationResult result = target.validate( - givenBid(builder -> builder.crid(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases); + givenBid(builder -> builder.crid(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases, null); // then assertThat(result.getErrors()).containsOnly("Bid \"bidId1\" missing creative ID"); @@ -146,7 +152,8 @@ public void validateShouldFailIfBidHasNoCrid() { public void validateShouldFailIfBannerBidHasNoWidthAndHeight() { // when final BidderBid givenBid = givenBid(builder -> builder.w(null).h(null)); - final ValidationResult result = target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); + final ValidationResult result = target.validate( + givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); // then assertThat(result.getErrors()) @@ -162,7 +169,8 @@ public void validateShouldFailIfBannerBidHasNoWidthAndHeight() { public void validateShouldFailIfBannerBidWidthIsGreaterThanImposedByImp() { // when final BidderBid givenBid = givenBid(builder -> builder.w(150).h(150)); - final ValidationResult result = target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); + final ValidationResult result = target.validate( + givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); // then assertThat(result.getErrors()) @@ -178,7 +186,8 @@ public void validateShouldFailIfBannerBidWidthIsGreaterThanImposedByImp() { public void validateShouldFailIfBannerBidHeightIsGreaterThanImposedByImp() { // when final BidderBid givenBid = givenBid(builder -> builder.w(50).h(250)); - final ValidationResult result = target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); + final ValidationResult result = target.validate( + givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); // then assertThat(result.getErrors()) @@ -197,7 +206,8 @@ public void validateShouldReturnSuccessIfNonBannerBidHasAnySize() { givenBid(BidType.video, builder -> builder.w(3).h(3)), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.hasErrors()).isFalse(); @@ -215,7 +225,8 @@ public void validateShouldTolerateMissingImpExtBidderNode() { givenBid(BidType.video, builder -> builder.w(3).h(3)), BIDDER_NAME, givenAuctionContext(bidRequest), - bidderAliases); + bidderAliases, + null); // then assertThat(result.hasErrors()).isFalse(); @@ -232,7 +243,8 @@ public void validateShouldReturnSuccessIfBannerBidHasInvalidSizeButAccountDoesNo givenAccount(builder -> builder.auction(AccountAuctionConfig.builder() .bidValidations(AccountBidValidationConfig.of(skip)) .build()))), - bidderAliases); + bidderAliases, + null); // then assertThat(result.hasErrors()).isFalse(); @@ -246,7 +258,8 @@ public void validateShouldFailIfBidHasNoCorrespondingImp() { givenBid(builder -> builder.impid("nonExistentsImpid")), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.getErrors()) @@ -262,7 +275,8 @@ public void validateShouldFailIfBidHasInsecureMarkerInCreativeInSecureContext() givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases); + bidderAliases, + null); // then assertThat(result.getErrors()) @@ -282,7 +296,8 @@ public void validateShouldFailIfBidHasInsecureEncodedMarkerInCreativeInSecureCon givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases); + bidderAliases, + null); // then assertThat(result.getErrors()) @@ -302,7 +317,8 @@ public void validateShouldFailIfBidHasNoSecureMarkersInCreativeInSecureContext() givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases); + bidderAliases, + null); // then assertThat(result.getErrors()) @@ -321,7 +337,8 @@ public void validateShouldReturnSuccessIfBidHasInsecureCreativeInInsecureContext givenBid(builder -> builder.adm("http://site.com/creative.jpg")), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.hasErrors()).isFalse(); @@ -335,7 +352,8 @@ public void validateShouldFailedIfVideoBidHasNoNurlAndAdm() { givenBid(BidType.video, builder -> builder.adm(null).nurl(null)), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.getErrors()) @@ -351,7 +369,8 @@ public void validateShouldReturnSuccessfulResultForValidVideoBidWithNurl() { givenBid(BidType.video, builder -> builder.adm(null)), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.hasErrors()).isFalse(); @@ -365,7 +384,8 @@ public void validateShouldReturnSuccessfulResultForValidVideoBidWithAdm() { givenBid(BidType.video, builder -> builder.nurl(null)), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.hasErrors()).isFalse(); @@ -379,7 +399,8 @@ public void validateShouldReturnSuccessfulResultForValidBid() { givenBid(identity()), BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases); + bidderAliases, + null); // then assertThat(result.hasErrors()).isFalse(); @@ -396,7 +417,7 @@ public void validateShouldReturnSuccessIfBannerSizeValidationNotEnabled() { givenBid(identity()), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, null); // then assertThat(result.hasErrors()).isFalse(); @@ -414,7 +435,8 @@ public void validateShouldReturnSuccessWithWarningIfBannerSizeEnforcementIsWarn( givenBid, BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.hasErrors()).isFalse(); @@ -436,7 +458,7 @@ public void validateShouldReturnSuccessIfSecureMarkupValidationNotEnabled() { givenBid(builder -> builder.adm("http://site.com/creative.jpg")), BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases); + bidderAliases, null); // then assertThat(result.hasErrors()).isFalse(); @@ -454,7 +476,7 @@ public void validateShouldReturnSuccessWithWarningIfSecureMarkupEnforcementIsWar givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases); + bidderAliases, null); // then assertThat(result.hasErrors()).isFalse(); @@ -470,7 +492,7 @@ public void validateShouldReturnSuccessWithWarningIfSecureMarkupEnforcementIsWar public void validateShouldIncrementSizeValidationErrMetrics() { // when final BidderBid givenBid = givenBid(builder -> builder.w(150).h(200)); - target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); + target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); // then verify(metrics).updateSizeValidationMetrics(BIDDER_NAME, ACCOUNT_ID, MetricName.err); @@ -485,7 +507,7 @@ public void validateShouldIncrementSizeValidationWarnMetrics() { // when final BidderBid givenBid = givenBid(builder -> builder.w(150).h(200)); - target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); + target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); // then verify(metrics).updateSizeValidationMetrics(BIDDER_NAME, ACCOUNT_ID, MetricName.warn); @@ -500,7 +522,8 @@ public void validateShouldIncrementSecureValidationErrMetrics() { givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases); + bidderAliases, + null); // then verify(metrics).updateSecureValidationMetrics(BIDDER_NAME, ACCOUNT_ID, MetricName.err); @@ -519,7 +542,8 @@ public void validateShouldIncrementSecureValidationWarnMetrics() { givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases); + bidderAliases, + null); // then verify(metrics).updateSecureValidationMetrics(BIDDER_NAME, ACCOUNT_ID, MetricName.warn); @@ -533,7 +557,8 @@ public void validateShouldNotFailOnSeatValidationWhenSeatEqualsToBidder() { givenBid(identity()).toBuilder().seat(BIDDER_NAME).build(), BIDDER_NAME, givenAuctionContext(), - bidderAliases); + bidderAliases, + null); // then assertThat(result.getWarnings()).isEmpty(); @@ -551,14 +576,14 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisable final ValidationResult result = target.validate( givenBid, BIDDER_NAME, - givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( - AccountAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() - .enabled(false) - .allowedBidderCodes(Set.of("seat")) - .build())).build()))), - bidderAliases); + givenAuctionContext(givenAccount(identity())), + bidderAliases, + ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() + .enabled(false) + .allowedBidderCodes(Set.of("seat")) + .build())).build()); // then assertThat(result.getWarnings()) @@ -569,7 +594,7 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisable } @Test - public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLackingSeatAlternateCode() { + public void validateShouldFailOnSeatValidationWhennullAreLackingSeatAlternateCode() { // given final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); @@ -577,14 +602,14 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLacking final ValidationResult result = target.validate( givenBid, BIDDER_NAME, - givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( - AccountAlternateBidderCodes.builder() + givenAuctionContext(givenAccount(identity())), + bidderAliases, + ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() .enabled(true) - .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("anotherSeat")) - .build())).build()))), - bidderAliases); + .allowedBidderCodes(Set.of("anotherSeat")) + .build())).build()); // then assertThat(result.getWarnings()) @@ -595,7 +620,7 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLacking } @Test - public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLackingBidder() { + public void validateShouldFailOnSeatValidationWhennullAreLackingBidder() { // given final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); @@ -603,12 +628,12 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLacking final ValidationResult result = target.validate( givenBid, BIDDER_NAME, - givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( - AccountAlternateBidderCodes.builder() - .enabled(true) - .bidders(null) - .build()))), - bidderAliases); + givenAuctionContext(givenAccount(identity())), + bidderAliases, + ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(null) + .build()); // then assertThat(result.getWarnings()) @@ -619,7 +644,7 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLacking } @Test - public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisabled() { + public void validateShouldFailOnSeatValidationWhennullAreDisabled() { // given final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); @@ -627,14 +652,14 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisable final ValidationResult result = target.validate( givenBid, BIDDER_NAME, - givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( - AccountAlternateBidderCodes.builder() - .enabled(false) - .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("seat")) - .build())).build()))), - bidderAliases); + givenAuctionContext(givenAccount(identity())), + bidderAliases, + ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(false) + .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("seat")) + .build())).build()); // then assertThat(result.getWarnings()) @@ -653,14 +678,14 @@ public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesAreNul final ValidationResult result = target.validate( givenBid, BIDDER_NAME, - givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( - AccountAlternateBidderCodes.builder() + givenAuctionContext(givenAccount(identity())), + bidderAliases, + ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() .enabled(true) - .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(null) - .build())).build()))), - bidderAliases); + .allowedBidderCodes(null) + .build())).build()); // then assertThat(result.getWarnings()).isEmpty(); @@ -678,14 +703,14 @@ public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContai final ValidationResult result = target.validate( givenBid, BIDDER_NAME, - givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( - AccountAlternateBidderCodes.builder() + givenAuctionContext(givenAccount(identity())), + bidderAliases, + ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() .enabled(true) - .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("*")) - .build())).build()))), - bidderAliases); + .allowedBidderCodes(Set.of("*")) + .build())).build()); // then assertThat(result.getWarnings()).isEmpty(); @@ -703,14 +728,14 @@ public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContai final ValidationResult result = target.validate( givenBid, BIDDER_NAME, - givenAuctionContext(givenAccount(account -> account.alternateBidderCodes( - AccountAlternateBidderCodes.builder() + givenAuctionContext(givenAccount(identity())), + bidderAliases, + ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() .enabled(true) - .bidders(Map.of(BIDDER_NAME, AccountAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("seat")) - .build())).build()))), - bidderAliases); + .allowedBidderCodes(Set.of("seat")) + .build())).build()); // then assertThat(result.getWarnings()).isEmpty(); From 0ca7246573110b7b0203dc22047ab8e1136addf6 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Wed, 5 Mar 2025 12:07:50 +0100 Subject: [PATCH 03/23] Fix bid rejection --- .../validation/ResponseBidValidator.java | 45 +++++++------------ .../validation/ResponseBidValidatorTest.java | 12 ++--- 2 files changed, 21 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java index bd3ca70f42b..bb05c7d4ce7 100644 --- a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java +++ b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java @@ -59,7 +59,7 @@ public class ResponseBidValidator { private static final String[] INSECURE_MARKUP_MARKERS = {"http:", "http%3A"}; private static final String[] SECURE_MARKUP_MARKERS = {"https:", "https%3A"}; - private static final String ALTERNATE_BIDDER_CODE_WILDCARD = "*"; + private static final String WILDCARD = "*"; private final BidValidationEnforcement bannerMaxSizeEnforcement; private final BidValidationEnforcement secureMarkupEnforcement; @@ -95,7 +95,7 @@ public ValidationResult validate(BidderBid bidderBid, validateCommonFields(bid); validateTypeSpecific(bidderBid, bidder); validateCurrency(bidderBid.getBidCurrency()); - validateSeat(bidderBid, bidder, account, bidRejectionTracker, alternateBidderCodes, warnings); + validateSeat(bidderBid, bidder, account, bidRejectionTracker, alternateBidderCodes); final Imp correspondingImp = findCorrespondingImp(bid, bidRequest); if (bidderBid.getType() == BidType.banner) { @@ -167,8 +167,7 @@ private void validateSeat(BidderBid bid, String bidder, Account account, BidRejectionTracker bidRejectionTracker, - ExtRequestPrebidAlternateBidderCodes alternateBidderCodes, - List warnings) { + ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) throws ValidationException { if (bid.getSeat() == null || StringUtils.equals(bid.getSeat(), bidder)) { return; @@ -178,19 +177,22 @@ private void validateSeat(BidderBid bid, bidder, alternateBidderCodes); - if (!isAlternateBidderCodesEnabled(alternateBidderCodes) || alternateBidder == null) { - warnings.add(rejectBidOnInvalidSeat(bid, bidder, account, bidRejectionTracker)); - return; - } - - final Set allowedBidderCodes = ObjectUtils.defaultIfNull( - alternateBidder.getAllowedBidderCodes(), - Collections.singleton(ALTERNATE_BIDDER_CODE_WILDCARD)); + if (isAlternateBidderCodesEnabled(alternateBidderCodes) && alternateBidder != null) { + final Set allowedBidderCodes = ObjectUtils.defaultIfNull( + alternateBidder.getAllowedBidderCodes(), + Collections.singleton(WILDCARD)); - if (!allowedBidderCodes.contains(ALTERNATE_BIDDER_CODE_WILDCARD) - && !allowedBidderCodes.contains(bid.getSeat())) { - warnings.add(rejectBidOnInvalidSeat(bid, bidder, account, bidRejectionTracker)); + if (allowedBidderCodes.contains(WILDCARD) || allowedBidderCodes.contains(bid.getSeat())) { + return; + } } + + final String message = "invalid bidder code %s was set by the adapter %s for the account %s" + .formatted(bid.getSeat(), bidder, account.getId()); + bidRejectionTracker.rejectBid(bid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); + metrics.updateSeatValidationMetrics(bidder); + ALTERNATE_BIDDER_CODE_LOGGER.warn(message, logSamplingRate); + throw new ValidationException(message); } private static Boolean isAlternateBidderCodesEnabled(ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { @@ -210,19 +212,6 @@ private static ExtRequestPrebidAlternateBidderCodesBidder resolveAlternateBidder .orElse(null); } - private String rejectBidOnInvalidSeat(BidderBid bid, - String bidder, - Account account, - BidRejectionTracker bidRejectionTracker) { - - final String message = "invalid bidder code %s was set by the adapter %s for the account %s" - .formatted(bid.getSeat(), bidder, account.getId()); - bidRejectionTracker.rejectBid(bid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); - metrics.updateSeatValidationMetrics(bidder); - ALTERNATE_BIDDER_CODE_LOGGER.warn(message, logSamplingRate); - return message; - } - private Imp findCorrespondingImp(Bid bid, BidRequest bidRequest) throws ValidationException { return bidRequest.getImp().stream() .filter(imp -> Objects.equals(imp.getId(), bid.getImpid())) diff --git a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java index 265f4331da5..4fa996a3bd2 100644 --- a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java @@ -586,9 +586,8 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisable .build())).build()); // then - assertThat(result.getWarnings()) + assertThat(result.getErrors()) .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); - assertThat(result.getErrors()).isEmpty(); verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); } @@ -612,9 +611,8 @@ public void validateShouldFailOnSeatValidationWhennullAreLackingSeatAlternateCod .build())).build()); // then - assertThat(result.getWarnings()) + assertThat(result.getErrors()) .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); - assertThat(result.getErrors()).isEmpty(); verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); } @@ -636,9 +634,8 @@ public void validateShouldFailOnSeatValidationWhennullAreLackingBidder() { .build()); // then - assertThat(result.getWarnings()) + assertThat(result.getErrors()) .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); - assertThat(result.getErrors()).isEmpty(); verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); } @@ -662,9 +659,8 @@ public void validateShouldFailOnSeatValidationWhennullAreDisabled() { .build())).build()); // then - assertThat(result.getWarnings()) + assertThat(result.getErrors()) .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); - assertThat(result.getErrors()).isEmpty(); verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); } From e242c3c29d18b2ad371a7212260d8ed380da5cec Mon Sep 17 00:00:00 2001 From: antonbabak Date: Wed, 5 Mar 2025 12:27:27 +0100 Subject: [PATCH 04/23] Fix tests --- .../it/openrtb2/adinify/test-auction-adinify-response.json | 5 ++++- .../server/it/openrtb2/adt/test-auction-adt-response.json | 5 ++++- .../artechnology/test-auction-artechnology-response.json | 5 ++++- .../it/openrtb2/jambojar/test-auction-jambojar-response.json | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adinify/test-auction-adinify-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adinify/test-auction-adinify-response.json index c1163d30d8c..f250edca1c2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adinify/test-auction-adinify-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adinify/test-auction-adinify-response.json @@ -18,7 +18,10 @@ "mediaType": "video", "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "adinify" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adt/test-auction-adt-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adt/test-auction-adt-response.json index c4f8a96adbf..044f26a4777 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adt/test-auction-adt-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adt/test-auction-adt-response.json @@ -13,7 +13,10 @@ "crid": "24080", "ext": { "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "adt" + } }, "origbidcpm": 0.01 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/artechnology/test-auction-artechnology-response.json b/src/test/resources/org/prebid/server/it/openrtb2/artechnology/test-auction-artechnology-response.json index 676d1ec67c0..a1b190da013 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/artechnology/test-auction-artechnology-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/artechnology/test-auction-artechnology-response.json @@ -18,7 +18,10 @@ "mediaType": "video", "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "artechnology" + } } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/jambojar/test-auction-jambojar-response.json b/src/test/resources/org/prebid/server/it/openrtb2/jambojar/test-auction-jambojar-response.json index f0af52f749f..852d757e414 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/jambojar/test-auction-jambojar-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/jambojar/test-auction-jambojar-response.json @@ -18,7 +18,10 @@ "mediaType": "video", "origbidcpm": 3.33, "prebid": { - "type": "video" + "type": "video", + "meta": { + "adaptercode": "jambojar" + } } } } From c76d2cde70e9b1e1740a5caf591d9ea79cb36913 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 6 Mar 2025 09:39:18 +0100 Subject: [PATCH 05/23] Fix mapping --- .../server/proto/openrtb/ext/request/ExtRequestPrebid.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java index 0667ac571c7..98754a459a5 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java @@ -191,6 +191,6 @@ public class ExtRequestPrebid { @JsonProperty("paaformat") PaaFormat paaFormat; - @JsonProperty("alternatebidderscodes") + @JsonProperty("alternatebiddercodes") ExtRequestPrebidAlternateBidderCodes alternateBidderCodes; } From 93f25737515fd0dd68ad3eda8faabad4451b6874 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 6 Mar 2025 09:56:46 +0100 Subject: [PATCH 06/23] Fix mapping --- .../request/ExtRequestPrebidAlternateBidderCodesBidder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java index d51d9dd8651..729f9627fab 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java @@ -1,6 +1,6 @@ package org.prebid.server.proto.openrtb.ext.request; -import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; import lombok.Value; @@ -12,6 +12,6 @@ public class ExtRequestPrebidAlternateBidderCodesBidder { Boolean enabled; - @JsonAlias("allowedbiddercodes") + @JsonProperty("allowedbiddercodes") Set allowedBidderCodes; } From 9226693032a8fd6438074122920e1bea6d769de4 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 6 Mar 2025 14:31:58 +0100 Subject: [PATCH 07/23] Add case-insensitive checks --- .../server/validation/ResponseBidValidator.java | 11 +++++++---- .../validation/ResponseBidValidatorTest.java | 16 ++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java index bb05c7d4ce7..942863db2e7 100644 --- a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java +++ b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java @@ -7,6 +7,7 @@ import com.iab.openrtb.request.Site; import com.iab.openrtb.response.Bid; import org.apache.commons.collections4.ListUtils; +import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; @@ -36,6 +37,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.TreeSet; import java.util.function.Consumer; /** @@ -169,7 +171,7 @@ private void validateSeat(BidderBid bid, BidRejectionTracker bidRejectionTracker, ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) throws ValidationException { - if (bid.getSeat() == null || StringUtils.equals(bid.getSeat(), bidder)) { + if (bid.getSeat() == null || StringUtils.equalsIgnoreCase(bid.getSeat(), bidder)) { return; } @@ -178,9 +180,9 @@ private void validateSeat(BidderBid bid, alternateBidderCodes); if (isAlternateBidderCodesEnabled(alternateBidderCodes) && alternateBidder != null) { - final Set allowedBidderCodes = ObjectUtils.defaultIfNull( - alternateBidder.getAllowedBidderCodes(), - Collections.singleton(WILDCARD)); + final Set allowedBidderCodes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + Optional.ofNullable(alternateBidder.getAllowedBidderCodes()) + .ifPresentOrElse(allowedBidderCodes::addAll, () -> allowedBidderCodes.add(WILDCARD)); if (allowedBidderCodes.contains(WILDCARD) || allowedBidderCodes.contains(bid.getSeat())) { return; @@ -207,6 +209,7 @@ private static ExtRequestPrebidAlternateBidderCodesBidder resolveAlternateBidder return Optional.ofNullable(alternateBidderCodes) .map(ExtRequestPrebidAlternateBidderCodes::getBidders) + .map(CaseInsensitiveMap::new) .map(bidders -> bidders.get(bidder)) .filter(alternate -> BooleanUtils.isTrue(alternate.getEnabled())) .orElse(null); diff --git a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java index 4fa996a3bd2..07ac0229896 100644 --- a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java @@ -551,10 +551,10 @@ public void validateShouldIncrementSecureValidationWarnMetrics() { } @Test - public void validateShouldNotFailOnSeatValidationWhenSeatEqualsToBidder() { + public void validateShouldNotFailOnSeatValidationWhenSeatEqualsIgnoringCaseToBidder() { // when final ValidationResult result = target.validate( - givenBid(identity()).toBuilder().seat(BIDDER_NAME).build(), + givenBid(identity()).toBuilder().seat("biDDEr").build(), BIDDER_NAME, givenAuctionContext(), bidderAliases, @@ -593,7 +593,7 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisable } @Test - public void validateShouldFailOnSeatValidationWhennullAreLackingSeatAlternateCode() { + public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLackingSeat() { // given final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); @@ -618,7 +618,7 @@ public void validateShouldFailOnSeatValidationWhennullAreLackingSeatAlternateCod } @Test - public void validateShouldFailOnSeatValidationWhennullAreLackingBidder() { + public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLackingBidders() { // given final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); @@ -641,7 +641,7 @@ public void validateShouldFailOnSeatValidationWhennullAreLackingBidder() { } @Test - public void validateShouldFailOnSeatValidationWhennullAreDisabled() { + public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisabled() { // given final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); @@ -716,7 +716,7 @@ public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContai } @Test - public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContainsSeat() { + public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContainsSeatCaseInsensitive() { // given final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); @@ -728,9 +728,9 @@ public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContai bidderAliases, ExtRequestPrebidAlternateBidderCodes.builder() .enabled(true) - .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() + .bidders(Map.of("BiDDEr", ExtRequestPrebidAlternateBidderCodesBidder.builder() .enabled(true) - .allowedBidderCodes(Set.of("seat")) + .allowedBidderCodes(Set.of("SeaT")) .build())).build()); // then From 6dd0a646c0af4ec70ec4b329aaa4f152bd67168c Mon Sep 17 00:00:00 2001 From: antonbabak Date: Fri, 7 Mar 2025 10:29:01 +0100 Subject: [PATCH 08/23] Fix soft aliases --- .../server/auction/ExchangeService.java | 8 ++- .../server/auction/ExchangeServiceTest.java | 55 ++++++++++++++++++- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index faeaffbebe2..f75ca8d1762 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -1247,15 +1247,17 @@ private Future requestBids(BidderRequest bidderRequest, requestHeaders, aliases, debugResolver.resolveDebugForBidder(auctionContext, resolvedBidderName))) - .map(seatBid -> populateBidderCode(seatBid, bidderName)) + .map(seatBid -> populateBidderCode(seatBid, bidderName, resolvedBidderName)) .map(seatBid -> BidderResponse.of(bidderName, seatBid, responseTime(bidderRequestStartTime))); } - private BidderSeatBid populateBidderCode(BidderSeatBid seatBid, String bidderName) { + private BidderSeatBid populateBidderCode(BidderSeatBid seatBid, String bidderName, String resolvedBidderName) { return seatBid.with(seatBid.getBids().stream() .map(bidderBid -> bidderBid.toBuilder() .seat(bidderBid.getSeat() == null ? bidderName : bidderBid.getSeat()) - .bid(bidderBid.getBid().toBuilder().ext(prepareBidExt(bidderBid.getBid(), bidderName)).build()) + .bid(bidderBid.getBid().toBuilder() + .ext(prepareBidExt(bidderBid.getBid(), resolvedBidderName)) + .build()) .build()) .toList()); } diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index 014390c61f5..5793f90ca76 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -3067,8 +3067,8 @@ public void shouldIncrementCommonMetrics() { public void shouldValidateBidsWithExtRequestPrebidAlternateBidderCodes() { // given given(httpBidderRequester.requestBids(any(), any(), any(), any(), any(), any(), anyBoolean())) - .willReturn(Future.succeededFuture(givenSeatBid(singletonList( - givenBidderBid(Bid.builder().impid("impId").price(TEN).build()))))); + .willReturn(Future.succeededFuture(givenSingleSeatBid( + givenBidderBid(Bid.builder().impid("impId").price(TEN).build())))); final ExtRequestPrebidAlternateBidderCodes requestAlternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder().enabled(false).build(); @@ -3125,6 +3125,57 @@ public void shouldValidateBidsWithAccountAlternateBidderCodesWhenRequestOnesAreA verify(bidsAdjuster).validateAndAdjustBids(any(), any(), any(), eq(accountAlternateBidderCodes)); } + @Test + public void shouldPopulateSoftAliasToSeatAndHardAliasToAdapterCodeWhenBidDoesNotHaveSeat() { + // given + given(bidderCatalog.isValidName("softAlias")).willReturn(false); + given(httpBidderRequester.requestBids(any(), any(), any(), any(), any(), any(), anyBoolean())) + .willReturn(Future.succeededFuture(givenSingleSeatBid( + givenBidderBid(Bid.builder().impid("impId").price(TEN).build())))); + + final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("softAlias", 1)), + builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .aliases(Map.of("softAlias", "hardAlias")) + .build()))); + + // when + final AuctionContext result = target.holdAuction(givenRequestContext(bidRequest)).result(); + + // then + assertThat(result.getAuctionParticipations()) + .extracting(AuctionParticipation::getBidderResponse) + .extracting(BidderResponse::getSeatBid) + .flatExtracting(BidderSeatBid::getBids) + .extracting( + BidderBid::getSeat, + bid -> bid.getBid().getExt().get("prebid").get("meta").get("adaptercode").asText()) + .containsOnly(tuple("softAlias", "hardAlias")); + } + + @Test + public void shouldPopulateSeatToSeatAndActualBidderToAdapterCodeWhenBidHasSeat() { + // given + given(httpBidderRequester.requestBids(any(), any(), any(), any(), any(), any(), anyBoolean())) + .willReturn(Future.succeededFuture(givenSingleSeatBid(BidderBid.of( + Bid.builder().impid("impId").price(TEN).build(), banner, "seat", null)))); + + final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1))); + + // when + final AuctionContext result = target.holdAuction(givenRequestContext(bidRequest)).result(); + + // then + assertThat(result.getAuctionParticipations()) + .extracting(AuctionParticipation::getBidderResponse) + .extracting(BidderResponse::getSeatBid) + .flatExtracting(BidderSeatBid::getBids) + .extracting( + BidderBid::getSeat, + bid -> bid.getBid().getExt().get("prebid").get("meta").get("adaptercode").asText()) + .containsOnly(tuple("seat", "someBidder")); + } + @Test public void shouldCallUpdateCookieMetricsWithExpectedValue() { // given From 0a5faa5085a32d3b8e5777a0a2a6d167e1f9ba8f Mon Sep 17 00:00:00 2001 From: antonbabak Date: Mon, 10 Mar 2025 16:34:20 +0100 Subject: [PATCH 09/23] Fix json mapping --- .../ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java | 2 ++ src/main/java/org/prebid/server/settings/model/Account.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java index 729f9627fab..7ca7f2fd79c 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java @@ -1,5 +1,6 @@ package org.prebid.server.proto.openrtb.ext.request; +import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; import lombok.Value; @@ -13,5 +14,6 @@ public class ExtRequestPrebidAlternateBidderCodesBidder { Boolean enabled; @JsonProperty("allowedbiddercodes") + @JsonAlias("allowed-bidder-codes") Set allowedBidderCodes; } diff --git a/src/main/java/org/prebid/server/settings/model/Account.java b/src/main/java/org/prebid/server/settings/model/Account.java index 5a937b4ebed..fabc222d94d 100644 --- a/src/main/java/org/prebid/server/settings/model/Account.java +++ b/src/main/java/org/prebid/server/settings/model/Account.java @@ -28,7 +28,7 @@ public class Account { AccountSettings settings; - @JsonAlias("alternatebiddercodes") + @JsonAlias("alternate-bidder-codes") ExtRequestPrebidAlternateBidderCodes alternateBidderCodes; public static Account empty(String id) { From 1c942780cc8aaa6690f05cb96d84d15bc3bf914b Mon Sep 17 00:00:00 2001 From: antonbabak Date: Tue, 11 Mar 2025 10:46:51 +0100 Subject: [PATCH 10/23] Fix comments --- .../server/auction/ExchangeService.java | 2 +- .../resetdigital/ResetDigitalBidder.java | 23 +++++++++----- .../org/prebid/server/util/BidderUtil.java | 31 ------------------- .../validation/ResponseBidValidator.java | 20 +++++------- 4 files changed, 24 insertions(+), 52 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index f75ca8d1762..afd49fcb3e5 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -1254,7 +1254,7 @@ private Future requestBids(BidderRequest bidderRequest, private BidderSeatBid populateBidderCode(BidderSeatBid seatBid, String bidderName, String resolvedBidderName) { return seatBid.with(seatBid.getBids().stream() .map(bidderBid -> bidderBid.toBuilder() - .seat(bidderBid.getSeat() == null ? bidderName : bidderBid.getSeat()) + .seat(ObjectUtils.defaultIfNull(bidderBid.getSeat(), bidderName)) .bid(bidderBid.getBid().toBuilder() .ext(prepareBidExt(bidderBid.getBid(), resolvedBidderName)) .build()) diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java b/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java index 09184177566..8604a2f8a80 100644 --- a/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java +++ b/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java @@ -10,6 +10,7 @@ import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; import io.vertx.core.MultiMap; +import io.vertx.core.http.HttpMethod; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.prebid.server.bidder.Bidder; @@ -32,7 +33,6 @@ import org.prebid.server.proto.openrtb.ext.ExtPrebid; import org.prebid.server.proto.openrtb.ext.request.resetdigital.ExtImpResetDigital; import org.prebid.server.proto.openrtb.ext.response.BidType; -import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; import java.util.ArrayList; @@ -65,13 +65,7 @@ public Result>> makeHttpRequests(BidReques try { final ExtImpResetDigital extImp = parseImpExt(imp); final ResetDigitalImp resetDigitalImp = makeImp(request, imp, extImp); - final HttpRequest httpRequest = BidderUtil.defaultRequest( - makeRequest(request, resetDigitalImp), - makeHeaders(request), - endpointUrl, - Set.of(resetDigitalImp.getImpId()), - mapper); - requests.add(httpRequest); + requests.add(makeHttpRequest(request, resetDigitalImp)); } catch (PreBidException e) { errors.add(BidderError.badInput(e.getMessage())); } @@ -146,6 +140,19 @@ private static boolean isValidSizeValue(Integer value) { return value != null && value > 0; } + private HttpRequest makeHttpRequest(BidRequest request, ResetDigitalImp resetDigitalImp) { + final ResetDigitalRequest modifiedRequest = makeRequest(request, resetDigitalImp); + + return HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(makeHeaders(request)) + .impIds(Set.of(resetDigitalImp.getImpId())) + .body(mapper.encodeToBytes(modifiedRequest)) + .payload(modifiedRequest) + .build(); + } + private static ResetDigitalRequest makeRequest(BidRequest request, ResetDigitalImp resetDigitalImp) { return ResetDigitalRequest.builder() .site(makeSite(request.getSite())) diff --git a/src/main/java/org/prebid/server/util/BidderUtil.java b/src/main/java/org/prebid/server/util/BidderUtil.java index 0895815670c..d6869e3b72d 100644 --- a/src/main/java/org/prebid/server/util/BidderUtil.java +++ b/src/main/java/org/prebid/server/util/BidderUtil.java @@ -33,21 +33,6 @@ public static HttpRequest defaultRequest(BidRequest bidRequest, return defaultRequest(bidRequest, HttpUtil.headers(), endpointUrl, mapper); } - public static HttpRequest defaultRequest(T bidRequest, - String endpointUrl, - Set impIds, - JacksonMapper mapper) { - - return HttpRequest.builder() - .method(HttpMethod.POST) - .uri(endpointUrl) - .headers(HttpUtil.headers()) - .impIds(impIds) - .body(mapper.encodeToBytes(bidRequest)) - .payload(bidRequest) - .build(); - } - public static HttpRequest defaultRequest(BidRequest bidRequest, MultiMap headers, String endpointUrl, @@ -62,22 +47,6 @@ public static HttpRequest defaultRequest(BidRequest bidRequest, .build(); } - public static HttpRequest defaultRequest(T bidRequest, - MultiMap headers, - String endpointUrl, - Set impIds, - JacksonMapper mapper) { - - return HttpRequest.builder() - .method(HttpMethod.POST) - .uri(endpointUrl) - .headers(headers) - .impIds(impIds) - .body(mapper.encodeToBytes(bidRequest)) - .payload(bidRequest) - .build(); - } - public static Set impIds(BidRequest bidRequest) { return bidRequest.getImp().stream() .map(Imp::getId) diff --git a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java index 942863db2e7..4d385ef8a10 100644 --- a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java +++ b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java @@ -46,18 +46,14 @@ public class ResponseBidValidator { private static final Logger logger = LoggerFactory.getLogger(ResponseBidValidator.class); - private static final ConditionalLogger UNRELATED_BID_LOGGER = new ConditionalLogger( - "not_matched_bid", - logger); - private static final ConditionalLogger SECURE_CREATIVE_LOGGER = new ConditionalLogger( - "secure_creatives_validation", - logger); - private static final ConditionalLogger CREATIVE_SIZE_LOGGER = new ConditionalLogger( - "creative_size_validation", - logger); - private static final ConditionalLogger ALTERNATE_BIDDER_CODE_LOGGER = new ConditionalLogger( - "alternate_bidder_code_validation", - logger); + private static final ConditionalLogger UNRELATED_BID_LOGGER = + new ConditionalLogger("not_matched_bid", logger); + private static final ConditionalLogger SECURE_CREATIVE_LOGGER = + new ConditionalLogger("secure_creatives_validation", logger); + private static final ConditionalLogger CREATIVE_SIZE_LOGGER = + new ConditionalLogger("creative_size_validation", logger); + private static final ConditionalLogger ALTERNATE_BIDDER_CODE_LOGGER = + new ConditionalLogger("alternate_bidder_code_validation", logger); private static final String[] INSECURE_MARKUP_MARKERS = {"http:", "http%3A"}; private static final String[] SECURE_MARKUP_MARKERS = {"https:", "https%3A"}; From c8715dcb540c86017b17f4c257aa9a8824906e06 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Wed, 12 Mar 2025 15:41:37 +0100 Subject: [PATCH 11/23] Fix comments + case-insensitive soft aliases --- .../prebid/server/auction/BidderAliases.java | 80 +++++- .../prebid/server/auction/BidsAdjuster.java | 13 +- .../server/auction/ExchangeService.java | 52 ++-- .../openrtb/ext/request/AlternateBidder.java | 10 + ...questPrebidAlternateBidderCodesBidder.java | 4 +- .../prebid/server/settings/model/Account.java | 3 +- .../model/AccountAlternateBidderCodes.java | 15 ++ .../AccountAlternateBidderCodesBidder.java | 18 ++ .../server/validation/ImpValidator.java | 5 +- .../server/validation/RequestValidator.java | 15 +- .../validation/ResponseBidValidator.java | 69 ++---- .../server/auction/BidderAliasesTest.java | 112 +++++++++ .../server/auction/BidsAdjusterTest.java | 18 +- .../server/auction/ExchangeServiceTest.java | 32 ++- .../validation/RequestValidatorTest.java | 20 ++ .../validation/ResponseBidValidatorTest.java | 228 +++--------------- 16 files changed, 378 insertions(+), 316 deletions(-) create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/AlternateBidder.java create mode 100644 src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java create mode 100644 src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java diff --git a/src/main/java/org/prebid/server/auction/BidderAliases.java b/src/main/java/org/prebid/server/auction/BidderAliases.java index 87ad01efe3b..986bbc03dcb 100644 --- a/src/main/java/org/prebid/server/auction/BidderAliases.java +++ b/src/main/java/org/prebid/server/auction/BidderAliases.java @@ -1,29 +1,47 @@ package org.prebid.server.auction; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.collections4.map.CaseInsensitiveMap; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.BidderCatalog; +import org.prebid.server.proto.openrtb.ext.request.AlternateBidder; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; +import org.prebid.server.settings.model.AccountAlternateBidderCodes; +import java.util.Collection; +import java.util.Collections; import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; +import java.util.function.Function; +import java.util.stream.Collectors; /** * Represents aliases configured for bidders - configuration might come in OpenRTB request but not limited to it. */ public class BidderAliases { + private static final String WILDCARD = "*"; + private final Map aliasToBidder; private final Map aliasToVendorId; + private final Map> bidderToAllowedBidderCodes; + private final BidderCatalog bidderCatalog; private BidderAliases(Map aliasToBidder, Map aliasToVendorId, + Map> bidderToAllowedBidderCodes, BidderCatalog bidderCatalog) { - this.aliasToBidder = MapUtils.emptyIfNull(aliasToBidder); - this.aliasToVendorId = MapUtils.emptyIfNull(aliasToVendorId); + this.aliasToBidder = new CaseInsensitiveMap<>(MapUtils.emptyIfNull(aliasToBidder)); + this.aliasToVendorId = new CaseInsensitiveMap<>(MapUtils.emptyIfNull(aliasToVendorId)); + this.bidderToAllowedBidderCodes = MapUtils.emptyIfNull(bidderToAllowedBidderCodes); this.bidderCatalog = Objects.requireNonNull(bidderCatalog); } @@ -31,7 +49,33 @@ public static BidderAliases of(Map aliasToBidder, Map aliasToVendorId, BidderCatalog bidderCatalog) { - return new BidderAliases(aliasToBidder, aliasToVendorId, bidderCatalog); + return new BidderAliases(aliasToBidder, aliasToVendorId, null, bidderCatalog); + } + + public static BidderAliases of(Map aliasToBidder, + Map aliasToVendorId, + BidderCatalog bidderCatalog, + AccountAlternateBidderCodes alternateBidderCodes) { + + final Map> bidderToAllowedSeats = resolveAlternateBidderCodes( + alternateBidderCodes, + AccountAlternateBidderCodes::getEnabled, + AccountAlternateBidderCodes::getBidders); + + return new BidderAliases(aliasToBidder, aliasToVendorId, bidderToAllowedSeats, bidderCatalog); + } + + public static BidderAliases of(Map aliasToBidder, + Map aliasToVendorId, + BidderCatalog bidderCatalog, + ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { + + final Map> bidderToAllowedSeats = resolveAlternateBidderCodes( + alternateBidderCodes, + ExtRequestPrebidAlternateBidderCodes::getEnabled, + ExtRequestPrebidAlternateBidderCodes::getBidders); + + return new BidderAliases(aliasToBidder, aliasToVendorId, bidderToAllowedSeats, bidderCatalog); } public boolean isAliasDefined(String alias) { @@ -57,4 +101,34 @@ private Integer resolveAliasVendorIdViaCatalog(String alias) { final String bidderName = resolveBidder(alias); return bidderCatalog.isActive(bidderName) ? bidderCatalog.vendorIdByName(bidderName) : null; } + + public boolean isAllowedAlternateBidderCode(String bidder, String alternateBidderCode) { + final Set allowedBidderCodes = bidderToAllowedBidderCodes.getOrDefault(bidder, Collections.emptySet()); + return allowedBidderCodes.contains(WILDCARD) || allowedBidderCodes.contains(alternateBidderCode); + } + + private static Map> resolveAlternateBidderCodes( + T alternateBidderCodes, + Function isEnabled, + Function> getBidders) { + + return Optional.ofNullable(alternateBidderCodes) + .filter(isEnabled::apply) + .map(getBidders::apply) + .map(Map::entrySet) + .stream() + .flatMap(Collection::stream) + .filter(entry -> BooleanUtils.isTrue(entry.getValue().getEnabled())) + .map(entry -> { + final Set allowedBidderCodes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + Optional.ofNullable(entry.getValue().getAllowedBidderCodes()) + .ifPresentOrElse(allowedBidderCodes::addAll, () -> allowedBidderCodes.add(WILDCARD)); + return Map.entry(entry.getKey(), allowedBidderCodes); + }) + .collect(Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (first, second) -> second, + CaseInsensitiveMap::new)); + } } diff --git a/src/main/java/org/prebid/server/auction/BidsAdjuster.java b/src/main/java/org/prebid/server/auction/BidsAdjuster.java index ffcf748af4f..39dd941eb43 100644 --- a/src/main/java/org/prebid/server/auction/BidsAdjuster.java +++ b/src/main/java/org/prebid/server/auction/BidsAdjuster.java @@ -10,7 +10,6 @@ import org.prebid.server.bidder.model.BidderError; import org.prebid.server.bidder.model.BidderSeatBid; import org.prebid.server.floors.PriceFloorEnforcer; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; import org.prebid.server.util.ObjectUtil; import org.prebid.server.validation.ResponseBidValidator; import org.prebid.server.validation.model.ValidationResult; @@ -41,15 +40,13 @@ public BidsAdjuster(ResponseBidValidator responseBidValidator, public List validateAndAdjustBids(List auctionParticipations, AuctionContext auctionContext, - BidderAliases aliases, - ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { + BidderAliases aliases) { return auctionParticipations.stream() .map(auctionParticipation -> validBidderResponse( auctionParticipation, auctionContext, - aliases, - alternateBidderCodes)) + aliases)) .map(auctionParticipation -> bidAdjustmentsProcessor.enrichWithAdjustedBids( auctionParticipation, @@ -71,8 +68,7 @@ public List validateAndAdjustBids(List BIDDER_FIELDS_EXCEPTION_LIST = Set.of( "adunitcode", "storedrequest", "options", "is_rewarded_inventory"); - private static final TypeReference> EXT_PREBID_TYPE_REFERENCE = - new TypeReference<>() { - }; private final double logSamplingRate; private final BidderCatalog bidderCatalog; @@ -241,13 +236,11 @@ private Future runAuction(AuctionContext receivedContext) { final MetricName requestTypeMetric = receivedContext.getRequestTypeMetric(); final List storedAuctionResponses = new ArrayList<>(); - final BidderAliases aliases = aliases(bidRequest); + final BidderAliases aliases = aliases(bidRequest, account); final BidRequestCacheInfo cacheInfo = bidRequestCacheInfo(bidRequest); final Map bidderToMultiBid = bidderToMultiBids(bidRequest, debugWarnings); receivedContext.getBidRejectionTrackers().putAll(makeBidRejectionTrackers(bidRequest, aliases)); - final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = getAlternateBidderCodes(bidRequest, account); - final boolean debugEnabled = receivedContext.getDebugContext().isDebugEnabled(); metrics.updateDebugRequestMetrics(debugEnabled); metrics.updateAccountDebugRequestMetrics(account, debugEnabled); @@ -281,8 +274,7 @@ private Future runAuction(AuctionContext receivedContext) { .map(auctionParticipations -> bidsAdjuster.validateAndAdjustBids( auctionParticipations, context, - aliases, - alternateBidderCodes)) + aliases)) .map(auctionParticipations -> updateResponsesMetrics(auctionParticipations, account, aliases)) .map(context::with)) // produce response from bidder results @@ -297,20 +289,17 @@ private Future runAuction(AuctionContext receivedContext) { .map(context::with)); } - private BidderAliases aliases(BidRequest bidRequest) { + private BidderAliases aliases(BidRequest bidRequest, Account account) { final ExtRequestPrebid prebid = PbsUtil.extRequestPrebid(bidRequest); final Map aliases = prebid != null ? prebid.getAliases() : null; final Map aliasgvlids = prebid != null ? prebid.getAliasgvlids() : null; - return BidderAliases.of(aliases, aliasgvlids, bidderCatalog); - } - - private static ExtRequestPrebidAlternateBidderCodes getAlternateBidderCodes(BidRequest bidRequest, - Account account) { + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = prebid != null + ? prebid.getAlternateBidderCodes() + : null; - return Optional.ofNullable(bidRequest.getExt()) - .map(ExtRequest::getPrebid) - .map(ExtRequestPrebid::getAlternateBidderCodes) - .orElse(account.getAlternateBidderCodes()); + return alternateBidderCodes != null + ? BidderAliases.of(aliases, aliasgvlids, bidderCatalog, alternateBidderCodes) + : BidderAliases.of(aliases, aliasgvlids, bidderCatalog, account.getAlternateBidderCodes()); } private static ExtRequestTargeting targeting(BidRequest bidRequest) { @@ -1264,9 +1253,10 @@ private BidderSeatBid populateBidderCode(BidderSeatBid seatBid, String bidderNam private ObjectNode prepareBidExt(Bid bid, String bidderName) { final ObjectNode bidExt = bid.getExt(); - final ExtPrebid extPrebid = getExtPrebid(bidExt); - final ExtBidPrebid extBidPrebid = extPrebid != null ? extPrebid.getPrebid() : null; - final ExtBidPrebidMeta meta = extBidPrebid != null ? extBidPrebid.getMeta() : null; + final ObjectNode extPrebid = bidExt != null ? (ObjectNode) bidExt.get(PREBID_EXT) : null; + final ExtBidPrebidMeta meta = extPrebid != null + ? getExtPrebidMeta(extPrebid.get(PREBID_META_EXT)) + : null; final ExtBidPrebidMeta updatedMeta = Optional.ofNullable(meta) .map(ExtBidPrebidMeta::toBuilder) @@ -1274,19 +1264,19 @@ private ObjectNode prepareBidExt(Bid bid, String bidderName) { .adapterCode(bidderName) .build(); - final ExtBidPrebid modifiedExtBidPrebid = extBidPrebid != null - ? extBidPrebid.toBuilder().meta(updatedMeta).build() - : ExtBidPrebid.builder().meta(updatedMeta).build(); - final ObjectNode updatedBidExt = bidExt != null ? bidExt : mapper.mapper().createObjectNode(); - updatedBidExt.set(PREBID_EXT, mapper.mapper().valueToTree(modifiedExtBidPrebid)); + final ObjectNode updatedBidExtPrebid = extPrebid != null ? extPrebid : mapper.mapper().createObjectNode(); + updatedBidExtPrebid.set(PREBID_META_EXT, mapper.mapper().valueToTree(updatedMeta)); + updatedBidExt.set(PREBID_EXT, mapper.mapper().valueToTree(updatedBidExtPrebid)); return updatedBidExt; } - private ExtPrebid getExtPrebid(ObjectNode bidExt) { + private ExtBidPrebidMeta getExtPrebidMeta(JsonNode bidExtPrebidMeta) { try { - return bidExt != null ? mapper.mapper().convertValue(bidExt, EXT_PREBID_TYPE_REFERENCE) : null; + return bidExtPrebidMeta != null + ? mapper.mapper().convertValue(bidExtPrebidMeta, ExtBidPrebidMeta.class) + : null; } catch (IllegalArgumentException e) { return null; } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/AlternateBidder.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/AlternateBidder.java new file mode 100644 index 00000000000..2c3a7866ebc --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/AlternateBidder.java @@ -0,0 +1,10 @@ +package org.prebid.server.proto.openrtb.ext.request; + +import java.util.Set; + +public interface AlternateBidder { + + Boolean getEnabled(); + + Set getAllowedBidderCodes(); +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java index 7ca7f2fd79c..1500a01c6c8 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java @@ -1,6 +1,5 @@ package org.prebid.server.proto.openrtb.ext.request; -import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; import lombok.Value; @@ -9,11 +8,10 @@ @Builder(toBuilder = true) @Value -public class ExtRequestPrebidAlternateBidderCodesBidder { +public class ExtRequestPrebidAlternateBidderCodesBidder implements AlternateBidder { Boolean enabled; @JsonProperty("allowedbiddercodes") - @JsonAlias("allowed-bidder-codes") Set allowedBidderCodes; } diff --git a/src/main/java/org/prebid/server/settings/model/Account.java b/src/main/java/org/prebid/server/settings/model/Account.java index fabc222d94d..4286c5077f0 100644 --- a/src/main/java/org/prebid/server/settings/model/Account.java +++ b/src/main/java/org/prebid/server/settings/model/Account.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.annotation.JsonAlias; import lombok.Builder; import lombok.Value; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; @Builder(toBuilder = true) @Value @@ -29,7 +28,7 @@ public class Account { AccountSettings settings; @JsonAlias("alternate-bidder-codes") - ExtRequestPrebidAlternateBidderCodes alternateBidderCodes; + AccountAlternateBidderCodes alternateBidderCodes; public static Account empty(String id) { return Account.builder().id(id).build(); diff --git a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java new file mode 100644 index 00000000000..ffbebc0d5c6 --- /dev/null +++ b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java @@ -0,0 +1,15 @@ +package org.prebid.server.settings.model; + +import lombok.Builder; +import lombok.Value; + +import java.util.Map; + +@Builder(toBuilder = true) +@Value +public class AccountAlternateBidderCodes { + + Boolean enabled; + + Map bidders; +} diff --git a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java new file mode 100644 index 00000000000..0ed42dbe70d --- /dev/null +++ b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java @@ -0,0 +1,18 @@ +package org.prebid.server.settings.model; + +import com.fasterxml.jackson.annotation.JsonAlias; +import lombok.Builder; +import lombok.Value; +import org.prebid.server.proto.openrtb.ext.request.AlternateBidder; + +import java.util.Set; + +@Builder(toBuilder = true) +@Value +public class AccountAlternateBidderCodesBidder implements AlternateBidder { + + Boolean enabled; + + @JsonAlias("allowed-bidder-codes") + Set allowedBidderCodes; +} diff --git a/src/main/java/org/prebid/server/validation/ImpValidator.java b/src/main/java/org/prebid/server/validation/ImpValidator.java index 986e63eca68..b2a2e3b0bed 100644 --- a/src/main/java/org/prebid/server/validation/ImpValidator.java +++ b/src/main/java/org/prebid/server/validation/ImpValidator.java @@ -361,8 +361,11 @@ private void validateNativeEventTracker(EventTracker eventTracker, int impIndex, } } - private void validateImpExt(ObjectNode ext, Map aliases, int impIndex, + private void validateImpExt(ObjectNode ext, + Map aliases, + int impIndex, List warnings) throws ValidationException { + validateImpExtPrebid(ext != null ? ext.get(PREBID_EXT) : null, aliases, impIndex, warnings); } diff --git a/src/main/java/org/prebid/server/validation/RequestValidator.java b/src/main/java/org/prebid/server/validation/RequestValidator.java index cf8a1dd2745..9e2196af27b 100644 --- a/src/main/java/org/prebid/server/validation/RequestValidator.java +++ b/src/main/java/org/prebid/server/validation/RequestValidator.java @@ -13,6 +13,7 @@ import com.iab.openrtb.request.User; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.auction.model.debug.DebugContext; @@ -133,10 +134,11 @@ public ValidationResult validate(Account account, if (targeting != null) { validateTargeting(targeting); } - aliases = ObjectUtils.defaultIfNull(extRequestPrebid.getAliases(), Collections.emptyMap()); + aliases = new CaseInsensitiveMap<>(MapUtils.emptyIfNull(extRequestPrebid.getAliases())); + validateAliases(aliases, warnings, account); validateAliasesGvlIds(extRequestPrebid, aliases); - validateBidAdjustmentFactors(extRequestPrebid.getBidadjustmentfactors(), aliases); + validateBidAdjustmentFactors(extRequestPrebid.getBidadjustmentfactors()); validateExtBidPrebidData(extRequestPrebid.getData(), aliases, isDebugEnabled, warnings); validateSchains(extRequestPrebid.getSchains()); } @@ -217,7 +219,8 @@ private void validateCur(List currencies) throws ValidationException { private void validateAliasesGvlIds(ExtRequestPrebid extRequestPrebid, Map aliases) throws ValidationException { - final Map aliasGvlIds = MapUtils.emptyIfNull(extRequestPrebid.getAliasgvlids()); + final Map aliasGvlIds = new CaseInsensitiveMap<>(MapUtils.emptyIfNull( + extRequestPrebid.getAliasgvlids())); for (Map.Entry aliasToGvlId : aliasGvlIds.entrySet()) { @@ -238,8 +241,8 @@ private void validateAliasesGvlIds(ExtRequestPrebid extRequestPrebid, } } - private void validateBidAdjustmentFactors(ExtRequestBidAdjustmentFactors adjustmentFactors, - Map aliases) throws ValidationException { + private void validateBidAdjustmentFactors(ExtRequestBidAdjustmentFactors adjustmentFactors) + throws ValidationException { final Map bidderAdjustments = adjustmentFactors != null ? adjustmentFactors.getAdjustments() @@ -530,7 +533,7 @@ private void validateAliases(Map aliases, List warnings, } } - if (alias.equals(coreBidder)) { + if (alias.equalsIgnoreCase(coreBidder)) { throw new ValidationException(""" request.ext.prebid.aliases.%s defines a no-op alias. \ Choose a different alias, or remove this entry""".formatted(alias)); diff --git a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java index 4d385ef8a10..242114516e3 100644 --- a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java +++ b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java @@ -7,8 +7,6 @@ import com.iab.openrtb.request.Site; import com.iab.openrtb.response.Bid; import org.apache.commons.collections4.ListUtils; -import org.apache.commons.collections4.map.CaseInsensitiveMap; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.auction.BidderAliases; @@ -23,8 +21,6 @@ import org.prebid.server.metric.Metrics; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.settings.model.Account; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodesBidder; import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.settings.model.AccountBidValidationConfig; import org.prebid.server.settings.model.BidValidationEnforcement; @@ -35,9 +31,6 @@ import java.util.Currency; import java.util.List; import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.TreeSet; import java.util.function.Consumer; /** @@ -57,7 +50,6 @@ public class ResponseBidValidator { private static final String[] INSECURE_MARKUP_MARKERS = {"http:", "http%3A"}; private static final String[] SECURE_MARKUP_MARKERS = {"https:", "https%3A"}; - private static final String WILDCARD = "*"; private final BidValidationEnforcement bannerMaxSizeEnforcement; private final BidValidationEnforcement secureMarkupEnforcement; @@ -80,8 +72,7 @@ public ResponseBidValidator(BidValidationEnforcement bannerMaxSizeEnforcement, public ValidationResult validate(BidderBid bidderBid, String bidder, AuctionContext auctionContext, - BidderAliases aliases, - ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { + BidderAliases aliases) { final Bid bid = bidderBid.getBid(); final BidRequest bidRequest = auctionContext.getBidRequest(); @@ -93,7 +84,7 @@ public ValidationResult validate(BidderBid bidderBid, validateCommonFields(bid); validateTypeSpecific(bidderBid, bidder); validateCurrency(bidderBid.getBidCurrency()); - validateSeat(bidderBid, bidder, account, bidRejectionTracker, alternateBidderCodes); + validateSeat(bidderBid, bidder, account, bidRejectionTracker, aliases); final Imp correspondingImp = findCorrespondingImp(bid, bidRequest); if (bidderBid.getType() == BidType.banner) { @@ -165,50 +156,20 @@ private void validateSeat(BidderBid bid, String bidder, Account account, BidRejectionTracker bidRejectionTracker, - ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) throws ValidationException { - - if (bid.getSeat() == null || StringUtils.equalsIgnoreCase(bid.getSeat(), bidder)) { - return; - } - - final ExtRequestPrebidAlternateBidderCodesBidder alternateBidder = resolveAlternateBidder( - bidder, - alternateBidderCodes); - - if (isAlternateBidderCodesEnabled(alternateBidderCodes) && alternateBidder != null) { - final Set allowedBidderCodes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - Optional.ofNullable(alternateBidder.getAllowedBidderCodes()) - .ifPresentOrElse(allowedBidderCodes::addAll, () -> allowedBidderCodes.add(WILDCARD)); - - if (allowedBidderCodes.contains(WILDCARD) || allowedBidderCodes.contains(bid.getSeat())) { - return; - } + BidderAliases bidderAliases) throws ValidationException { + + final String seat = bid.getSeat(); + if (seat != null + && !StringUtils.equalsIgnoreCase(bidder, seat) + && !bidderAliases.isAllowedAlternateBidderCode(bidder, seat)) { + + final String message = "invalid bidder code %s was set by the adapter %s for the account %s" + .formatted(bid.getSeat(), bidder, account.getId()); + bidRejectionTracker.rejectBid(bid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); + metrics.updateSeatValidationMetrics(bidder); + ALTERNATE_BIDDER_CODE_LOGGER.warn(message, logSamplingRate); + throw new ValidationException(message); } - - final String message = "invalid bidder code %s was set by the adapter %s for the account %s" - .formatted(bid.getSeat(), bidder, account.getId()); - bidRejectionTracker.rejectBid(bid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); - metrics.updateSeatValidationMetrics(bidder); - ALTERNATE_BIDDER_CODE_LOGGER.warn(message, logSamplingRate); - throw new ValidationException(message); - } - - private static Boolean isAlternateBidderCodesEnabled(ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { - return Optional.ofNullable(alternateBidderCodes) - .map(ExtRequestPrebidAlternateBidderCodes::getEnabled) - .orElse(false); - } - - private static ExtRequestPrebidAlternateBidderCodesBidder resolveAlternateBidder( - String bidder, - ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { - - return Optional.ofNullable(alternateBidderCodes) - .map(ExtRequestPrebidAlternateBidderCodes::getBidders) - .map(CaseInsensitiveMap::new) - .map(bidders -> bidders.get(bidder)) - .filter(alternate -> BooleanUtils.isTrue(alternate.getEnabled())) - .orElse(null); } private Imp findCorrespondingImp(Bid bid, BidRequest bidRequest) throws ValidationException { diff --git a/src/test/java/org/prebid/server/auction/BidderAliasesTest.java b/src/test/java/org/prebid/server/auction/BidderAliasesTest.java index 30fc23a21fa..ac0a2137cb6 100644 --- a/src/test/java/org/prebid/server/auction/BidderAliasesTest.java +++ b/src/test/java/org/prebid/server/auction/BidderAliasesTest.java @@ -6,8 +6,11 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.bidder.BidderCatalog; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodesBidder; import java.util.Map; +import java.util.Set; import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; @@ -191,4 +194,113 @@ public void resolveAliasVendorIdShouldReturnVendorIdFromBidderCatalogWhenVendorI // when and then assertThat(aliases.resolveAliasVendorId("alias")).isEqualTo(3); } + + @Test + public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreDisabledForBidder() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() + .enabled(false) + .allowedBidderCodes(Set.of("seat")) + .build())) + .build(); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); + + // when and then + assertThat(aliases.isAllowedAlternateBidderCode("bidder", "seat")).isFalse(); + } + + @Test + public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreLackingSeat() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("anotherSeat")) + .build())) + .build(); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); + + // when and then + assertThat(aliases.isAllowedAlternateBidderCode("bidder", "seat")).isFalse(); + } + + @Test + public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreLackingBidders() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(null) + .build(); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); + + // when and then + assertThat(aliases.isAllowedAlternateBidderCode("bidder", "seat")).isFalse(); + } + + @Test + public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreDisabled() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(false) + .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("seat")) + .build())) + .build(); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); + + // when and then + assertThat(aliases.isAllowedAlternateBidderCode("bidder", "seat")).isFalse(); + } + + @Test + public void isAllowedAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCodesAreNull() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(null) + .build())) + .build(); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); + + // when and then + assertThat(aliases.isAllowedAlternateBidderCode("bidder", "seat")).isTrue(); + } + + @Test + public void isAllowedAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCodesContainsWildcard() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("*")) + .build())) + .build(); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); + + // when and then + assertThat(aliases.isAllowedAlternateBidderCode("bidder", "seat")).isTrue(); + } + + @Test + public void isAllowedAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCodesContainsSeatCaseInsensitive() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of("BiDDEr", ExtRequestPrebidAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("SeaT")) + .build())) + .build(); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); + + // when and then + assertThat(aliases.isAllowedAlternateBidderCode("bidder", "seat")).isTrue(); + } } diff --git a/src/test/java/org/prebid/server/auction/BidsAdjusterTest.java b/src/test/java/org/prebid/server/auction/BidsAdjusterTest.java index 927cf297b44..9bfbc9cb143 100644 --- a/src/test/java/org/prebid/server/auction/BidsAdjusterTest.java +++ b/src/test/java/org/prebid/server/auction/BidsAdjusterTest.java @@ -61,7 +61,7 @@ public class BidsAdjusterTest extends VertxTest { @BeforeEach public void setUp() { - given(responseBidValidator.validate(any(), any(), any(), any(), any())).willReturn(ValidationResult.success()); + given(responseBidValidator.validate(any(), any(), any(), any())).willReturn(ValidationResult.success()); given(priceFloorEnforcer.enforce(any(), any(), any(), any())).willAnswer(inv -> inv.getArgument(1)); given(dsaEnforcer.enforce(any(), any(), any())).willAnswer(inv -> inv.getArgument(1)); @@ -100,7 +100,7 @@ public void shouldReturnBidsAdjustedByBidAdjustmentsProcessor() { // when final List result = target.validateAndAdjustBids( - auctionParticipations, auctionContext, null, null); + auctionParticipations, auctionContext, null); // then assertThat(result) @@ -142,7 +142,7 @@ public void shouldReturnBidsAcceptedByPriceFloorEnforcer() { // when final List result = target.validateAndAdjustBids( - auctionParticipations, auctionContext, null, null); + auctionParticipations, auctionContext, null); // then assertThat(result) @@ -185,7 +185,7 @@ public void shouldReturnBidsAcceptedByDsaEnforcer() { // when final List result = target - .validateAndAdjustBids(auctionParticipations, auctionContext, null, null); + .validateAndAdjustBids(auctionParticipations, auctionContext, null); // then assertThat(result) @@ -213,7 +213,7 @@ public void shouldTolerateResponseBidValidationErrors() { .auctiontimestamp(1000L) .build()))); - when(responseBidValidator.validate(any(), any(), any(), any(), any())) + when(responseBidValidator.validate(any(), any(), any(), any())) .thenReturn(ValidationResult.error("Error: bid validation error.")); final List auctionParticipations = givenAuctionParticipation(bidderResponse, bidRequest); @@ -221,7 +221,7 @@ public void shouldTolerateResponseBidValidationErrors() { // when final List result = target - .validateAndAdjustBids(auctionParticipations, auctionContext, null, null); + .validateAndAdjustBids(auctionParticipations, auctionContext, null); // then assertThat(result) @@ -256,7 +256,7 @@ public void shouldTolerateResponseBidValidationWarnings() { .auctiontimestamp(1000L) .build()))); - when(responseBidValidator.validate(any(), any(), any(), any(), any())) + when(responseBidValidator.validate(any(), any(), any(), any())) .thenReturn(ValidationResult.warning(singletonList("Error: bid validation warning."))); final List auctionParticipations = givenAuctionParticipation(bidderResponse, bidRequest); @@ -264,7 +264,7 @@ public void shouldTolerateResponseBidValidationWarnings() { // when final List result = target - .validateAndAdjustBids(auctionParticipations, auctionContext, null, null); + .validateAndAdjustBids(auctionParticipations, auctionContext, null); // then assertThat(result) @@ -301,7 +301,7 @@ public void shouldAddWarningAboutMultipleCurrency() { // when final List result = target - .validateAndAdjustBids(auctionParticipations, auctionContext, null, null); + .validateAndAdjustBids(auctionParticipations, auctionContext, null); // then assertThat(result).hasSize(1); diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index 5793f90ca76..c0b02e8b9a0 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -147,6 +147,8 @@ import org.prebid.server.proto.openrtb.ext.response.ExtResponseDebug; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountAlternateBidderCodes; +import org.prebid.server.settings.model.AccountAlternateBidderCodesBidder; import org.prebid.server.settings.model.AccountAnalyticsConfig; import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.settings.model.AccountEventsConfig; @@ -166,6 +168,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.function.Function; import java.util.function.UnaryOperator; @@ -352,7 +355,7 @@ public void setUp() { false, AuctionResponsePayloadImpl.of(invocation.getArgument(0))))); - given(bidsAdjuster.validateAndAdjustBids(any(), any(), any(), any())) + given(bidsAdjuster.validateAndAdjustBids(any(), any(), any())) .willAnswer(invocation -> invocation.getArgument(0)); given(mediaTypeProcessor.process(any(), anyString(), any(), any())) @@ -3079,8 +3082,14 @@ public void shouldValidateBidsWithExtRequestPrebidAlternateBidderCodes() { .alternateBidderCodes(requestAlternateBidderCodes) .build()))); - final ExtRequestPrebidAlternateBidderCodes accountAlternateBidderCodes = - ExtRequestPrebidAlternateBidderCodes.builder().enabled(true).build(); + final AccountAlternateBidderCodes accountAlternateBidderCodes = + AccountAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of("someBidder", AccountAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("seat")) + .build())) + .build(); final Account givenAccount = Account.builder() .id("accountId") @@ -3094,7 +3103,8 @@ public void shouldValidateBidsWithExtRequestPrebidAlternateBidderCodes() { target.holdAuction(givenRequestContext(bidRequest, givenAccount)); // then - verify(bidsAdjuster).validateAndAdjustBids(any(), any(), any(), eq(requestAlternateBidderCodes)); + verify(bidsAdjuster).validateAndAdjustBids( + any(), any(), argThat(aliases -> !aliases.isAllowedAlternateBidderCode("someBidder", "seat"))); } @Test @@ -3107,8 +3117,14 @@ public void shouldValidateBidsWithAccountAlternateBidderCodesWhenRequestOnesAreA final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1)), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder().build()))); - final ExtRequestPrebidAlternateBidderCodes accountAlternateBidderCodes = - ExtRequestPrebidAlternateBidderCodes.builder().enabled(true).build(); + final AccountAlternateBidderCodes accountAlternateBidderCodes = + AccountAlternateBidderCodes.builder() + .enabled(true) + .bidders(Map.of("someBidder", AccountAlternateBidderCodesBidder.builder() + .enabled(true) + .allowedBidderCodes(Set.of("seat")) + .build())) + .build(); final Account givenAccount = Account.builder() .id("accountId") @@ -3122,7 +3138,9 @@ public void shouldValidateBidsWithAccountAlternateBidderCodesWhenRequestOnesAreA target.holdAuction(givenRequestContext(bidRequest, givenAccount)); // then - verify(bidsAdjuster).validateAndAdjustBids(any(), any(), any(), eq(accountAlternateBidderCodes)); + verify(bidsAdjuster).validateAndAdjustBids( + any(), any(), argThat(aliases -> aliases.isAllowedAlternateBidderCode("someBidder", "seat"))); + } @Test diff --git a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java index 8c3cac67d8f..709aab3e682 100644 --- a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java @@ -1183,6 +1183,26 @@ public void validateShouldReturnValidationMessageWhenAliasNameEqualsToBidderItPo Choose a different alias, or remove this entry"""); } + @Test + public void validateShouldReturnValidationMessageWhenAliasNameEqualsToBidderItPointsOnCaseInsensitive() { + // given + final ExtRequest ext = ExtRequest.of(ExtRequestPrebid.builder() + .aliases(singletonMap("RUBICOn", "ruBIcon")) + .build()); + final BidRequest bidRequest = validBidRequestBuilder().ext(ext).build(); + given(bidderCatalog.isValidName("ruBIcon")).willReturn(true); + given(bidderCatalog.isActive("ruBIcon")).willReturn(true); + + // when + final ValidationResult result = target.validate(Account.empty(ACCOUNT_ID), bidRequest, null, null); + + // then + assertThat(result.getErrors()).hasSize(1) + .containsOnly(""" + request.ext.prebid.aliases.rubicon defines a no-op alias. \ + Choose a different alias, or remove this entry"""); + } + @Test public void validateShouldReturnValidationErrorMessageWhenAliasPointOnNotValidBidderName() { // given diff --git a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java index 07ac0229896..af8590e38de 100644 --- a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java @@ -19,8 +19,6 @@ import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodesBidder; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAuctionConfig; @@ -29,7 +27,6 @@ import java.math.BigDecimal; import java.util.Map; -import java.util.Set; import java.util.function.UnaryOperator; import static java.util.Arrays.asList; @@ -68,6 +65,7 @@ public void setUp() { target = new ResponseBidValidator(enforce, enforce, metrics, 0.01); given(bidderAliases.resolveBidder(anyString())).willReturn(BIDDER_NAME); + given(bidderAliases.isAllowedAlternateBidderCode(anyString(), anyString())).willReturn(true); } @Test @@ -77,8 +75,7 @@ public void validateShouldFailedIfBidderBidCurrencyIsIncorrect() { givenBid(BidType.banner, "invalid", identity()), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.getErrors()).containsOnly("BidResponse currency \"invalid\" is not valid"); @@ -92,8 +89,7 @@ public void validateShouldFailIfMissingBid() { BidderBid.of(null, null, "USD"), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.getErrors()).containsOnly("Empty bid object submitted"); @@ -104,7 +100,7 @@ public void validateShouldFailIfMissingBid() { public void validateShouldFailIfBidHasNoId() { // when final ValidationResult result = target.validate( - givenBid(builder -> builder.id(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases, null); + givenBid(builder -> builder.id(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases); // then assertThat(result.getErrors()).containsOnly("Bid missing required field 'id'"); @@ -115,7 +111,7 @@ public void validateShouldFailIfBidHasNoId() { public void validateShouldFailIfBidHasNoImpId() { // when final ValidationResult result = target.validate( - givenBid(builder -> builder.impid(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases, null); + givenBid(builder -> builder.impid(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases); // then assertThat(result.getErrors()).containsOnly("Bid \"bidId1\" missing required field 'impid'"); @@ -129,8 +125,7 @@ public void validateShouldSuccessForDealZeroPriceBid() { givenVideoBid(builder -> builder.price(BigDecimal.valueOf(0)).dealid("dealId")), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -141,7 +136,7 @@ public void validateShouldSuccessForDealZeroPriceBid() { public void validateShouldFailIfBidHasNoCrid() { // when final ValidationResult result = target.validate( - givenBid(builder -> builder.crid(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases, null); + givenBid(builder -> builder.crid(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases); // then assertThat(result.getErrors()).containsOnly("Bid \"bidId1\" missing creative ID"); @@ -153,7 +148,7 @@ public void validateShouldFailIfBannerBidHasNoWidthAndHeight() { // when final BidderBid givenBid = givenBid(builder -> builder.w(null).h(null)); final ValidationResult result = target.validate( - givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); + givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); // then assertThat(result.getErrors()) @@ -170,7 +165,7 @@ public void validateShouldFailIfBannerBidWidthIsGreaterThanImposedByImp() { // when final BidderBid givenBid = givenBid(builder -> builder.w(150).h(150)); final ValidationResult result = target.validate( - givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); + givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); // then assertThat(result.getErrors()) @@ -187,7 +182,7 @@ public void validateShouldFailIfBannerBidHeightIsGreaterThanImposedByImp() { // when final BidderBid givenBid = givenBid(builder -> builder.w(50).h(250)); final ValidationResult result = target.validate( - givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); + givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); // then assertThat(result.getErrors()) @@ -206,8 +201,7 @@ public void validateShouldReturnSuccessIfNonBannerBidHasAnySize() { givenBid(BidType.video, builder -> builder.w(3).h(3)), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -225,8 +219,7 @@ public void validateShouldTolerateMissingImpExtBidderNode() { givenBid(BidType.video, builder -> builder.w(3).h(3)), BIDDER_NAME, givenAuctionContext(bidRequest), - bidderAliases, - null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -243,8 +236,7 @@ public void validateShouldReturnSuccessIfBannerBidHasInvalidSizeButAccountDoesNo givenAccount(builder -> builder.auction(AccountAuctionConfig.builder() .bidValidations(AccountBidValidationConfig.of(skip)) .build()))), - bidderAliases, - null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -258,8 +250,7 @@ public void validateShouldFailIfBidHasNoCorrespondingImp() { givenBid(builder -> builder.impid("nonExistentsImpid")), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.getErrors()) @@ -275,8 +266,7 @@ public void validateShouldFailIfBidHasInsecureMarkerInCreativeInSecureContext() givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases, - null); + bidderAliases); // then assertThat(result.getErrors()) @@ -296,8 +286,7 @@ public void validateShouldFailIfBidHasInsecureEncodedMarkerInCreativeInSecureCon givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases, - null); + bidderAliases); // then assertThat(result.getErrors()) @@ -317,8 +306,7 @@ public void validateShouldFailIfBidHasNoSecureMarkersInCreativeInSecureContext() givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases, - null); + bidderAliases); // then assertThat(result.getErrors()) @@ -337,8 +325,7 @@ public void validateShouldReturnSuccessIfBidHasInsecureCreativeInInsecureContext givenBid(builder -> builder.adm("http://site.com/creative.jpg")), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -352,8 +339,7 @@ public void validateShouldFailedIfVideoBidHasNoNurlAndAdm() { givenBid(BidType.video, builder -> builder.adm(null).nurl(null)), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.getErrors()) @@ -369,8 +355,7 @@ public void validateShouldReturnSuccessfulResultForValidVideoBidWithNurl() { givenBid(BidType.video, builder -> builder.adm(null)), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -384,8 +369,7 @@ public void validateShouldReturnSuccessfulResultForValidVideoBidWithAdm() { givenBid(BidType.video, builder -> builder.nurl(null)), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -399,8 +383,7 @@ public void validateShouldReturnSuccessfulResultForValidBid() { givenBid(identity()), BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases, - null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -417,7 +400,7 @@ public void validateShouldReturnSuccessIfBannerSizeValidationNotEnabled() { givenBid(identity()), BIDDER_NAME, givenAuctionContext(), - bidderAliases, null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -435,8 +418,7 @@ public void validateShouldReturnSuccessWithWarningIfBannerSizeEnforcementIsWarn( givenBid, BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -458,7 +440,7 @@ public void validateShouldReturnSuccessIfSecureMarkupValidationNotEnabled() { givenBid(builder -> builder.adm("http://site.com/creative.jpg")), BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases, null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -476,7 +458,7 @@ public void validateShouldReturnSuccessWithWarningIfSecureMarkupEnforcementIsWar givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases, null); + bidderAliases); // then assertThat(result.hasErrors()).isFalse(); @@ -492,7 +474,7 @@ public void validateShouldReturnSuccessWithWarningIfSecureMarkupEnforcementIsWar public void validateShouldIncrementSizeValidationErrMetrics() { // when final BidderBid givenBid = givenBid(builder -> builder.w(150).h(200)); - target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); + target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); // then verify(metrics).updateSizeValidationMetrics(BIDDER_NAME, ACCOUNT_ID, MetricName.err); @@ -507,7 +489,7 @@ public void validateShouldIncrementSizeValidationWarnMetrics() { // when final BidderBid givenBid = givenBid(builder -> builder.w(150).h(200)); - target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases, null); + target.validate(givenBid, BIDDER_NAME, givenAuctionContext(), bidderAliases); // then verify(metrics).updateSizeValidationMetrics(BIDDER_NAME, ACCOUNT_ID, MetricName.warn); @@ -522,8 +504,7 @@ public void validateShouldIncrementSecureValidationErrMetrics() { givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases, - null); + bidderAliases); // then verify(metrics).updateSecureValidationMetrics(BIDDER_NAME, ACCOUNT_ID, MetricName.err); @@ -542,8 +523,7 @@ public void validateShouldIncrementSecureValidationWarnMetrics() { givenBid, BIDDER_NAME, givenAuctionContext(givenBidRequest(builder -> builder.secure(1))), - bidderAliases, - null); + bidderAliases); // then verify(metrics).updateSecureValidationMetrics(BIDDER_NAME, ACCOUNT_ID, MetricName.warn); @@ -557,8 +537,7 @@ public void validateShouldNotFailOnSeatValidationWhenSeatEqualsIgnoringCaseToBid givenBid(identity()).toBuilder().seat("biDDEr").build(), BIDDER_NAME, givenAuctionContext(), - bidderAliases, - null); + bidderAliases); // then assertThat(result.getWarnings()).isEmpty(); @@ -568,22 +547,17 @@ public void validateShouldNotFailOnSeatValidationWhenSeatEqualsIgnoringCaseToBid } @Test - public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisabledForBidder() { + public void validateShouldFailOnSeatValidationWhenSeatIsNotAllowed() { // given final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); + given(bidderAliases.isAllowedAlternateBidderCode(BIDDER_NAME, "seat")).willReturn(false); // when final ValidationResult result = target.validate( givenBid, BIDDER_NAME, givenAuctionContext(givenAccount(identity())), - bidderAliases, - ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(false) - .allowedBidderCodes(Set.of("seat")) - .build())).build()); + bidderAliases); // then assertThat(result.getErrors()) @@ -593,145 +567,17 @@ public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisable } @Test - public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLackingSeat() { + public void validateShouldNotFailOnSeatValidationWhenSeatIsAllowed() { // given final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); + given(bidderAliases.isAllowedAlternateBidderCode(BIDDER_NAME, "seat")).willReturn(true); // when final ValidationResult result = target.validate( givenBid, BIDDER_NAME, givenAuctionContext(givenAccount(identity())), - bidderAliases, - ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("anotherSeat")) - .build())).build()); - - // then - assertThat(result.getErrors()) - .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); - verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); - verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); - } - - @Test - public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreLackingBidders() { - // given - final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); - - // when - final ValidationResult result = target.validate( - givenBid, - BIDDER_NAME, - givenAuctionContext(givenAccount(identity())), - bidderAliases, - ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(null) - .build()); - - // then - assertThat(result.getErrors()) - .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); - verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); - verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); - } - - @Test - public void validateShouldFailOnSeatValidationWhenAlternateBidderCodesAreDisabled() { - // given - final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); - - // when - final ValidationResult result = target.validate( - givenBid, - BIDDER_NAME, - givenAuctionContext(givenAccount(identity())), - bidderAliases, - ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(false) - .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("seat")) - .build())).build()); - - // then - assertThat(result.getErrors()) - .containsOnly("invalid bidder code seat was set by the adapter bidder for the account account"); - verify(metrics).updateSeatValidationMetrics(BIDDER_NAME); - verify(bidRejectionTracker).rejectBid(givenBid, BidRejectionReason.RESPONSE_REJECTED_GENERAL); - } - - @Test - public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesAreNull() { - // given - final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); - - // when - final ValidationResult result = target.validate( - givenBid, - BIDDER_NAME, - givenAuctionContext(givenAccount(identity())), - bidderAliases, - ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(null) - .build())).build()); - - // then - assertThat(result.getWarnings()).isEmpty(); - assertThat(result.getErrors()).isEmpty(); - verify(metrics, never()).updateSeatValidationMetrics(BIDDER_NAME); - verifyNoInteractions(bidRejectionTracker); - } - - @Test - public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContainsWildcard() { - // given - final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); - - // when - final ValidationResult result = target.validate( - givenBid, - BIDDER_NAME, - givenAuctionContext(givenAccount(identity())), - bidderAliases, - ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of(BIDDER_NAME, ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("*")) - .build())).build()); - - // then - assertThat(result.getWarnings()).isEmpty(); - assertThat(result.getErrors()).isEmpty(); - verify(metrics, never()).updateSeatValidationMetrics(BIDDER_NAME); - verifyNoInteractions(bidRejectionTracker); - } - - @Test - public void validateShouldNotFailOnSeatValidationWhenAllowedAlternateCodesContainsSeatCaseInsensitive() { - // given - final BidderBid givenBid = givenBid(identity()).toBuilder().seat("seat").build(); - - // when - final ValidationResult result = target.validate( - givenBid, - BIDDER_NAME, - givenAuctionContext(givenAccount(identity())), - bidderAliases, - ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of("BiDDEr", ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("SeaT")) - .build())).build()); + bidderAliases); // then assertThat(result.getWarnings()).isEmpty(); From df14a12af6ddcbfc13a0f2223ddbe36ea5671c9d Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 13 Mar 2025 11:00:10 +0100 Subject: [PATCH 12/23] NPE fix --- .../org/prebid/server/auction/BidderAliases.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/BidderAliases.java b/src/main/java/org/prebid/server/auction/BidderAliases.java index 986bbc03dcb..7b36a90c049 100644 --- a/src/main/java/org/prebid/server/auction/BidderAliases.java +++ b/src/main/java/org/prebid/server/auction/BidderAliases.java @@ -113,22 +113,24 @@ private static Map> resolveAlternateBidderCodes( Function> getBidders) { return Optional.ofNullable(alternateBidderCodes) - .filter(isEnabled::apply) + .filter(codes -> BooleanUtils.isTrue(isEnabled.apply(codes))) .map(getBidders::apply) .map(Map::entrySet) .stream() .flatMap(Collection::stream) .filter(entry -> BooleanUtils.isTrue(entry.getValue().getEnabled())) - .map(entry -> { - final Set allowedBidderCodes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - Optional.ofNullable(entry.getValue().getAllowedBidderCodes()) - .ifPresentOrElse(allowedBidderCodes::addAll, () -> allowedBidderCodes.add(WILDCARD)); - return Map.entry(entry.getKey(), allowedBidderCodes); - }) + .map(entry -> Map.entry(entry.getKey(), allowedBidderCodes(entry.getValue()))) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (first, second) -> second, CaseInsensitiveMap::new)); } + + private static Set allowedBidderCodes(AlternateBidder alternateBidder) { + final Set allowedBidderCodes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + Optional.ofNullable(alternateBidder.getAllowedBidderCodes()) + .ifPresentOrElse(allowedBidderCodes::addAll, () -> allowedBidderCodes.add(WILDCARD)); + return allowedBidderCodes; + } } From 734b2abe04cb6c88ed5a5254cb552e045a910a39 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 13 Mar 2025 13:38:05 +0100 Subject: [PATCH 13/23] Fix adapter code case --- .../server/auction/ExchangeService.java | 4 +++- .../prebid/server/bidder/BidderCatalog.java | 7 ++++++ .../server/auction/ExchangeServiceTest.java | 1 + .../server/bidder/BidderCatalogTest.java | 22 +++++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index 7e33743abad..0b5df3ed25b 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -1245,7 +1245,9 @@ private BidderSeatBid populateBidderCode(BidderSeatBid seatBid, String bidderNam .map(bidderBid -> bidderBid.toBuilder() .seat(ObjectUtils.defaultIfNull(bidderBid.getSeat(), bidderName)) .bid(bidderBid.getBid().toBuilder() - .ext(prepareBidExt(bidderBid.getBid(), resolvedBidderName)) + .ext(prepareBidExt( + bidderBid.getBid(), + bidderCatalog.configuredName(resolvedBidderName))) .build()) .build()) .toList()); diff --git a/src/main/java/org/prebid/server/bidder/BidderCatalog.java b/src/main/java/org/prebid/server/bidder/BidderCatalog.java index 3d8db57e941..fd2cb0dd930 100644 --- a/src/main/java/org/prebid/server/bidder/BidderCatalog.java +++ b/src/main/java/org/prebid/server/bidder/BidderCatalog.java @@ -226,4 +226,11 @@ public Bidder bidderByName(String name) { .map(BidderInstanceDeps::getBidder) .orElse(null); } + + public String configuredName(String name) { + return Optional.ofNullable(name) + .map(bidderDepsMap::get) + .map(BidderInstanceDeps::getName) + .orElse(null); + } } diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index c0b02e8b9a0..c1007ad9329 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -317,6 +317,7 @@ public void setUp() { CompressionType.NONE, Ortb.of(false), 0L)); + given(bidderCatalog.configuredName(anyString())).willAnswer(invocation -> invocation.getArgument(0)); given(privacyEnforcementService.mask(any(), argThat(MapUtils::isNotEmpty), any())) .willAnswer(inv -> diff --git a/src/test/java/org/prebid/server/bidder/BidderCatalogTest.java b/src/test/java/org/prebid/server/bidder/BidderCatalogTest.java index 44a3253c143..347279cd3b5 100644 --- a/src/test/java/org/prebid/server/bidder/BidderCatalogTest.java +++ b/src/test/java/org/prebid/server/bidder/BidderCatalogTest.java @@ -395,4 +395,26 @@ public void bidderByNameShouldReturnNullForUnknownBidder() { // when and then assertThat(target.bidderByName("unknown_bidder")).isNull(); } + + @Test + public void configuredNameShouldReturnOriginalBidderNameForKnownBidderIgnoringCase() { + // given + final BidderDeps bidderDeps = BidderDeps.of(singletonList(BidderInstanceDeps.builder() + .name("BIDder") + .deprecatedNames(emptyList()) + .build())); + target = new BidderCatalog(singletonList(bidderDeps)); + + // when and then + assertThat(target.configuredName("bidDER")).isEqualTo("BIDder"); + } + + @Test + public void configuredNameShouldReturnNullForUnknownBidder() { + // given + target = new BidderCatalog(emptyList()); + + // when and then + assertThat(target.configuredName("unknown_bidder")).isNull(); + } } From 06acd4dd92aa339e8c38e69ce55188cdcb0d7d5d Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 13 Mar 2025 14:07:37 +0100 Subject: [PATCH 14/23] Fix adapter code case --- .../lemmaDigital/test-auction-lemmaDigital-response.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lemmaDigital/test-auction-lemmaDigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/lemmaDigital/test-auction-lemmaDigital-response.json index 30c8205ffdf..dbb331eb850 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lemmaDigital/test-auction-lemmaDigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lemmaDigital/test-auction-lemmaDigital-response.json @@ -14,7 +14,7 @@ "prebid": { "type": "banner", "meta": { - "adaptercode": "lemmaDigital" + "adaptercode": "lemmadigital" } } } From afc31dcf9fb761096e06efb9b626027fb463a45d Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 13 Mar 2025 16:12:55 +0100 Subject: [PATCH 15/23] Remove ResetDigital Adapter Changes --- .../resetdigital/ResetDigitalBidder.java | 285 ++++---- .../resetdigital/request/ResetDigitalImp.java | 19 - .../request/ResetDigitalImpExt.java | 9 - .../request/ResetDigitalImpMediaType.java | 15 - .../request/ResetDigitalImpMediaTypes.java | 27 - .../request/ResetDigitalImpZone.java | 11 - .../request/ResetDigitalRequest.java | 15 - .../request/ResetDigitalSite.java | 13 - .../response/ResetDigitalBid.java | 31 - .../response/ResetDigitalResponse.java | 11 - .../bidder/ResetDigitalConfiguration.java | 7 +- .../resources/bidder-config/resetdigital.yaml | 5 +- .../static/bidder-params/resetdigital.json | 22 +- .../resetdigital/ResetDigitalBidderTest.java | 617 +++++++++--------- .../test-auction-resetdigital-request.json | 23 +- .../test-auction-resetdigital-response.json | 19 +- .../test-resetdigital-bid-request.json | 64 +- .../test-resetdigital-bid-response.json | 29 +- 18 files changed, 526 insertions(+), 696 deletions(-) delete mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImp.java delete mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpExt.java delete mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaType.java delete mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaTypes.java delete mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpZone.java delete mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalRequest.java delete mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalSite.java delete mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalBid.java delete mode 100644 src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalResponse.java diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java b/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java index 8604a2f8a80..3bc78b588b0 100644 --- a/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java +++ b/src/main/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidder.java @@ -1,249 +1,182 @@ package org.prebid.server.bidder.resetdigital; -import com.fasterxml.jackson.core.type.TypeReference; -import com.iab.openrtb.request.Audio; -import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Site; -import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; -import io.vertx.core.MultiMap; -import io.vertx.core.http.HttpMethod; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; import org.prebid.server.bidder.model.BidderError; import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.Price; import org.prebid.server.bidder.model.Result; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalImp; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpMediaType; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpMediaTypes; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpZone; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalRequest; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalSite; -import org.prebid.server.bidder.resetdigital.response.ResetDigitalBid; -import org.prebid.server.bidder.resetdigital.response.ResetDigitalResponse; +import org.prebid.server.currency.CurrencyConversionService; import org.prebid.server.exception.PreBidException; import org.prebid.server.json.DecodeException; import org.prebid.server.json.JacksonMapper; -import org.prebid.server.proto.openrtb.ext.ExtPrebid; -import org.prebid.server.proto.openrtb.ext.request.resetdigital.ExtImpResetDigital; import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; +import java.math.BigDecimal; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Set; +import java.util.stream.Stream; -public class ResetDigitalBidder implements Bidder { +public class ResetDigitalBidder implements Bidder { - private static final TypeReference> IMP_EXT_TYPE_REFERENCE = - new TypeReference<>() { - }; - private static final String BID_CURRENCY = "USD"; + private static final String DEFAULT_CURRENCY = "USD"; private final String endpointUrl; + private final CurrencyConversionService currencyConversionService; private final JacksonMapper mapper; - public ResetDigitalBidder(String endpointUrl, JacksonMapper mapper) { + public ResetDigitalBidder(String endpointUrl, + CurrencyConversionService currencyConversionService, + JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.currencyConversionService = Objects.requireNonNull(currencyConversionService); this.mapper = Objects.requireNonNull(mapper); } @Override - public Result>> makeHttpRequests(BidRequest request) { - final List> requests = new ArrayList<>(); - final List errors = new ArrayList<>(); + public Result>> makeHttpRequests(BidRequest request) { + final List bannerImps = new ArrayList<>(); + final List videoImps = new ArrayList<>(); + final List audioImps = new ArrayList<>(); + Price bidFloorPrice; - for (Imp imp: request.getImp()) { + for (Imp imp : request.getImp()) { try { - final ExtImpResetDigital extImp = parseImpExt(imp); - final ResetDigitalImp resetDigitalImp = makeImp(request, imp, extImp); - requests.add(makeHttpRequest(request, resetDigitalImp)); + bidFloorPrice = resolveBidFloor(imp, request); } catch (PreBidException e) { - errors.add(BidderError.badInput(e.getMessage())); + return Result.withError(BidderError.badInput(e.getMessage())); } + populateBannerImps(bannerImps, bidFloorPrice, imp); + populateVideoImps(videoImps, bidFloorPrice, imp); + populateAudiImps(audioImps, bidFloorPrice, imp); } - return Result.of(requests, errors); - } - - private ExtImpResetDigital parseImpExt(Imp imp) throws PreBidException { - try { - return mapper.mapper().convertValue(imp.getExt(), IMP_EXT_TYPE_REFERENCE).getBidder(); - } catch (IllegalArgumentException e) { - throw new PreBidException(e.getMessage()); - } + return Result.withValues(getHttpRequests(request, bannerImps, videoImps, audioImps)); } - private static ResetDigitalImp makeImp(BidRequest request, Imp imp, ExtImpResetDigital extImp) { - return ResetDigitalImp.builder() - .bidId(request.getId()) - .impId(imp.getId()) - .mediaTypes(resolveMediaTypes(imp)) - .zoneId(extImp.getPlacementId() == null ? null : ResetDigitalImpZone.of(extImp.getPlacementId())) - .build(); - } + private List> getHttpRequests(BidRequest request, + List bannerImps, + List videoImps, + List audioImps) { - private static ResetDigitalImpMediaTypes resolveMediaTypes(Imp imp) { - final Banner banner = imp.getBanner(); - final Video video = imp.getVideo(); - final Audio audio = imp.getAudio(); - - if (banner != null) { - final ResetDigitalImpMediaType mediaType = makeBanner(banner); - return mediaType == null ? null : ResetDigitalImpMediaTypes.banner(mediaType); - } else if (video != null) { - final ResetDigitalImpMediaType mediaType = makeVideo(video); - return mediaType == null ? null : ResetDigitalImpMediaTypes.video(mediaType); - } else if (audio != null) { - final ResetDigitalImpMediaType mediaType = makeAudio(audio); - return mediaType == null ? null : ResetDigitalImpMediaTypes.audio(mediaType); - } else { - throw new PreBidException("Banner, video or audio must be present in the imp %s".formatted(imp.getId())); - } + return Stream.of(bannerImps, videoImps, audioImps) + .filter(CollectionUtils::isNotEmpty) + .map(imp -> makeHttpRequest(request, imp)) + .toList(); } - private static ResetDigitalImpMediaType makeBanner(Banner banner) { - return makeMediaType(banner.getW(), banner.getH(), null); - } + private HttpRequest makeHttpRequest(BidRequest bidRequest, List imp) { + final BidRequest outgoingRequest = bidRequest.toBuilder().imp(imp).build(); - private static ResetDigitalImpMediaType makeVideo(Video video) { - return makeMediaType(video.getW(), video.getH(), video.getMimes()); + return BidderUtil.defaultRequest(outgoingRequest, endpointUrl, mapper); } - private static ResetDigitalImpMediaType makeAudio(Audio audio) { - return makeMediaType(null, null, audio.getMimes()); - } - - private static ResetDigitalImpMediaType makeMediaType(Integer width, Integer height, List mimes) { - final boolean hasValidSizes = isValidSizeValue(width) && isValidSizeValue(height); - final boolean hasMimes = CollectionUtils.isNotEmpty(mimes); - - if (!hasValidSizes && !hasMimes) { - return null; - } - - return ResetDigitalImpMediaType.builder() - .sizes(hasValidSizes ? List.of(List.of(width, height)) : null) - .mimes(hasMimes ? mimes : null) + private static Imp modifyImp(Imp imp, Price bidFloorPrice) { + return imp.toBuilder() + .bidfloorcur(bidFloorPrice.getCurrency()) + .bidfloor(bidFloorPrice.getValue()) .build(); } - private static boolean isValidSizeValue(Integer value) { - return value != null && value > 0; + private Price resolveBidFloor(Imp imp, BidRequest bidRequest) { + final Price initialBidFloorPrice = Price.of(imp.getBidfloorcur(), imp.getBidfloor()); + return BidderUtil.isValidPrice(initialBidFloorPrice) + ? convertBidFloor(initialBidFloorPrice, imp.getId(), bidRequest) + : initialBidFloorPrice; } - private HttpRequest makeHttpRequest(BidRequest request, ResetDigitalImp resetDigitalImp) { - final ResetDigitalRequest modifiedRequest = makeRequest(request, resetDigitalImp); - - return HttpRequest.builder() - .method(HttpMethod.POST) - .uri(endpointUrl) - .headers(makeHeaders(request)) - .impIds(Set.of(resetDigitalImp.getImpId())) - .body(mapper.encodeToBytes(modifiedRequest)) - .payload(modifiedRequest) - .build(); - } - - private static ResetDigitalRequest makeRequest(BidRequest request, ResetDigitalImp resetDigitalImp) { - return ResetDigitalRequest.builder() - .site(makeSite(request.getSite())) - .imps(Collections.singletonList(resetDigitalImp)) - .build(); + private Price convertBidFloor(Price bidFloorPrice, String impId, BidRequest bidRequest) { + final String bidFloorCur = bidFloorPrice.getCurrency(); + try { + final BigDecimal convertedPrice = currencyConversionService + .convertCurrency(bidFloorPrice.getValue(), bidRequest, bidFloorCur, DEFAULT_CURRENCY); + + return Price.of(DEFAULT_CURRENCY, convertedPrice); + } catch (PreBidException e) { + throw new PreBidException( + "Unable to convert provided bid floor currency from %s to %s for imp `%s`" + .formatted(bidFloorCur, DEFAULT_CURRENCY, impId)); + } } - private static ResetDigitalSite makeSite(Site site) { - return site == null || ObjectUtils.allNull(site.getDomain(), site.getPage()) - ? null - : ResetDigitalSite.builder() - .domain(site.getDomain()) - .referrer(site.getPage()) - .build(); + private static void populateBannerImps(List bannerImps, Price bidFloorPrice, Imp imp) { + if (imp.getBanner() != null) { + final Imp bannerImp = imp.toBuilder().video(null).xNative(null).audio(null).build(); + bannerImps.add(modifyImp(bannerImp, bidFloorPrice)); + } } - private static MultiMap makeHeaders(BidRequest request) { - final MultiMap headers = HttpUtil.headers(); - - final Device device = request.getDevice(); - if (device != null) { - HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.ACCEPT_LANGUAGE_HEADER, device.getLanguage()); - HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.USER_AGENT_HEADER, device.getUa()); - HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_FORWARDED_FOR_HEADER, device.getIp()); - HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_REAL_IP_HEADER, device.getIp()); + private static void populateVideoImps(List videoImps, Price bidFloorPrice, Imp imp) { + if (imp.getVideo() != null) { + final Imp videoImp = imp.toBuilder().banner(null).xNative(null).audio(null).build(); + videoImps.add(modifyImp(videoImp, bidFloorPrice)); } + } - final Site site = request.getSite(); - if (site != null) { - HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.REFERER_HEADER, site.getPage()); + private static void populateAudiImps(List audioImps, Price bidFloorPrice, Imp imp) { + if (imp.getAudio() != null) { + final Imp audioImp = imp.toBuilder().banner(null).xNative(null).video(null).build(); + audioImps.add(modifyImp(audioImp, bidFloorPrice)); } - - return headers; } @Override - public Result> makeBids(BidderCall httpCall, BidRequest bidRequest) { + public final Result> makeBids(BidderCall httpCall, BidRequest bidRequest) { try { - final ResetDigitalResponse bidResponse = mapper.decodeValue( - httpCall.getResponse().getBody(), - ResetDigitalResponse.class); - return Result.withValues(extractBids(bidRequest, bidResponse)); + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.withValues(extractBids(bidResponse, httpCall.getRequest().getPayload())); } catch (DecodeException | PreBidException e) { return Result.withError(BidderError.badServerResponse(e.getMessage())); } } - private static List extractBids(BidRequest bidRequest, ResetDigitalResponse bidResponse) { - final List bids = bidResponse == null - ? Collections.emptyList() - : CollectionUtils.emptyIfNull(bidResponse.getBids()).stream().filter(Objects::nonNull).toList(); - - if (bids.size() != 1) { - throw new PreBidException("expected exactly one bid in the response, but got %d".formatted(bids.size())); + private static List extractBids(BidResponse bidResponse, BidRequest bidRequest) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); } - - final ResetDigitalBid bid = bids.getFirst(); - final Imp correspondingImp = bidRequest.getImp().stream() - .filter(imp -> Objects.equals(imp.getId(), bid.getImpId())) - .findFirst() - .orElseThrow(() -> new PreBidException( - "no matching impression found for ImpID %s".formatted(bid.getImpId()))); - - return Collections.singletonList( - BidderBid.of(makeBid(bid), resolveBidType(correspondingImp), bid.getSeat(), BID_CURRENCY)); - } - - private static Bid makeBid(ResetDigitalBid bid) { - try { - return Bid.builder() - .id(bid.getBidId()) - .price(bid.getCpm()) - .impid(bid.getImpId()) - .cid(bid.getCid()) - .crid(bid.getCrid()) - .adm(bid.getHtml()) - .w(Integer.parseInt(bid.getW())) - .h(Integer.parseInt(bid.getH())) - .build(); - } catch (NumberFormatException e) { - throw new PreBidException(e.getMessage()); + if (bidResponse.getCur() != null && !StringUtils.equalsIgnoreCase(DEFAULT_CURRENCY, bidResponse.getCur())) { + throw new PreBidException("Bidder support only USD currency"); } - } - - private static BidType resolveBidType(Imp imp) throws PreBidException { - if (imp.getVideo() != null) { - return BidType.video; - } else if (imp.getAudio() != null) { - return BidType.audio; - } else { - return BidType.banner; + return bidsFromResponse(bidResponse, bidRequest); + } + + private static List bidsFromResponse(BidResponse bidResponse, BidRequest bidRequest) { + return bidResponse.getSeatbid().stream() + .filter(Objects::nonNull) + .map(SeatBid::getBid) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .map(bid -> BidderBid.of(bid, getBidType(bid, bidRequest.getImp()), DEFAULT_CURRENCY)) + .toList(); + } + + private static BidType getBidType(Bid bid, List imps) { + final String impId = bid.getImpid(); + for (Imp imp : imps) { + if (imp.getId().equals(impId)) { + if (imp.getBanner() != null) { + return BidType.banner; + } else if (imp.getVideo() != null) { + return BidType.video; + } else if (imp.getAudio() != null) { + return BidType.audio; + } + } } + throw new PreBidException("Failed to find banner/video/audio impression " + impId); } } diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImp.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImp.java deleted file mode 100644 index 5674c2446a7..00000000000 --- a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImp.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.prebid.server.bidder.resetdigital.request; - -import lombok.Builder; -import lombok.Value; - -@Value -@Builder -public class ResetDigitalImp { - - ResetDigitalImpZone zoneId; - - String bidId; - - String impId; - - ResetDigitalImpMediaTypes mediaTypes; - - ResetDigitalImpExt ext; -} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpExt.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpExt.java deleted file mode 100644 index 16363a5e6d9..00000000000 --- a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpExt.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.prebid.server.bidder.resetdigital.request; - -import lombok.Value; - -@Value(staticConstructor = "of") -public class ResetDigitalImpExt { - - String gpid; -} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaType.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaType.java deleted file mode 100644 index 5ee15918c38..00000000000 --- a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaType.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.bidder.resetdigital.request; - -import lombok.Builder; -import lombok.Value; - -import java.util.List; - -@Value(staticConstructor = "of") -@Builder -public class ResetDigitalImpMediaType { - - List> sizes; - - List mimes; -} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaTypes.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaTypes.java deleted file mode 100644 index 7483f318e0e..00000000000 --- a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpMediaTypes.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.prebid.server.bidder.resetdigital.request; - -import lombok.Builder; -import lombok.Value; - -@Value(staticConstructor = "of") -@Builder -public class ResetDigitalImpMediaTypes { - - ResetDigitalImpMediaType banner; - - ResetDigitalImpMediaType video; - - ResetDigitalImpMediaType audio; - - public static ResetDigitalImpMediaTypes banner(ResetDigitalImpMediaType banner) { - return ResetDigitalImpMediaTypes.builder().banner(banner).build(); - } - - public static ResetDigitalImpMediaTypes video(ResetDigitalImpMediaType video) { - return ResetDigitalImpMediaTypes.builder().video(video).build(); - } - - public static ResetDigitalImpMediaTypes audio(ResetDigitalImpMediaType audio) { - return ResetDigitalImpMediaTypes.builder().audio(audio).build(); - } -} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpZone.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpZone.java deleted file mode 100644 index 516ee7ec8bd..00000000000 --- a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalImpZone.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.prebid.server.bidder.resetdigital.request; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Value; - -@Value(staticConstructor = "of") -public class ResetDigitalImpZone { - - @JsonProperty("placementId") - String placementId; -} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalRequest.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalRequest.java deleted file mode 100644 index 8294ec1a469..00000000000 --- a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalRequest.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.bidder.resetdigital.request; - -import lombok.Builder; -import lombok.Value; - -import java.util.List; - -@Value -@Builder -public class ResetDigitalRequest { - - ResetDigitalSite site; - - List imps; -} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalSite.java b/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalSite.java deleted file mode 100644 index 77962b232b2..00000000000 --- a/src/main/java/org/prebid/server/bidder/resetdigital/request/ResetDigitalSite.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.bidder.resetdigital.request; - -import lombok.Builder; -import lombok.Value; - -@Value -@Builder -public class ResetDigitalSite { - - String domain; - - String referrer; -} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalBid.java b/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalBid.java deleted file mode 100644 index fead0572112..00000000000 --- a/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalBid.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.prebid.server.bidder.resetdigital.response; - -import lombok.Builder; -import lombok.Value; - -import java.math.BigDecimal; - -@Value(staticConstructor = "of") -@Builder -public class ResetDigitalBid { - - String bidId; - - String impId; - - BigDecimal cpm; - - String cid; - - String crid; - - String adid; - - String w; - - String h; - - String seat; - - String html; -} diff --git a/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalResponse.java b/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalResponse.java deleted file mode 100644 index 2dcf57e8d80..00000000000 --- a/src/main/java/org/prebid/server/bidder/resetdigital/response/ResetDigitalResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.prebid.server.bidder.resetdigital.response; - -import lombok.Value; - -import java.util.List; - -@Value(staticConstructor = "of") -public class ResetDigitalResponse { - - List bids; -} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ResetDigitalConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ResetDigitalConfiguration.java index 33823866d5f..4e4de161f66 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ResetDigitalConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ResetDigitalConfiguration.java @@ -2,6 +2,7 @@ import org.prebid.server.bidder.BidderDeps; import org.prebid.server.bidder.resetdigital.ResetDigitalBidder; +import org.prebid.server.currency.CurrencyConversionService; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; @@ -30,12 +31,16 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps resetDigitalBidderDeps(BidderConfigurationProperties resetDigitalConfigurationProperties, @NotBlank @Value("${external-url}") String externalUrl, + CurrencyConversionService currencyConversionService, JacksonMapper mapper) { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(resetDigitalConfigurationProperties) .usersyncerCreator(UsersyncerCreator.create(externalUrl)) - .bidderCreator(config -> new ResetDigitalBidder(config.getEndpoint(), mapper)) + .bidderCreator(config -> new ResetDigitalBidder( + config.getEndpoint(), + currencyConversionService, + mapper)) .assemble(); } } diff --git a/src/main/resources/bidder-config/resetdigital.yaml b/src/main/resources/bidder-config/resetdigital.yaml index 3ae9e26bf3e..885916d0d8d 100644 --- a/src/main/resources/bidder-config/resetdigital.yaml +++ b/src/main/resources/bidder-config/resetdigital.yaml @@ -4,6 +4,9 @@ adapters: meta-info: maintainer-email: biddersupport@resetdigital.co app-media-types: + - banner + - video + - audio site-media-types: - banner - video @@ -13,6 +16,6 @@ adapters: usersync: cookie-family-name: resetdigital redirect: - url: https://sync.resetdigital.co/csync?redir={{redirect_url}} + url: https://sync.resetdigital.co/csync?pid=rubicon&redir={{redirect_url}} support-cors: false uid-macro: '$USER_ID' diff --git a/src/main/resources/static/bidder-params/resetdigital.json b/src/main/resources/static/bidder-params/resetdigital.json index 07a7bc2b551..3710cfbc598 100644 --- a/src/main/resources/static/bidder-params/resetdigital.json +++ b/src/main/resources/static/bidder-params/resetdigital.json @@ -1,13 +1,23 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Reset Digital Adapter Params", - "description": "A schema which validates params accepted by the Reset Digital adapter", + "title": "ResetDigital Adapter Params", + "description": "A schema which validates params accepted by the ResetDigital adapter", "type": "object", "properties": { - "placement_id": { + "pubId": { "type": "string", - "minLength": 1, - "description": "Placement ID for the Reset Digital ad unit. This is the identifier for the ad unit on the Reset Digital platform, and its optional" + "description": "The publisher's ID provided" + }, + "zoneId": { + "type": "string", + "description": "Zone ID" + }, + "forceBid": { + "type": "boolean", + "description": "Force bids with a test creative" } - } + }, + "required": [ + "pubId" + ] } diff --git a/src/test/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidderTest.java b/src/test/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidderTest.java index 9bd1656433e..dbcc555489a 100644 --- a/src/test/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/resetdigital/ResetDigitalBidderTest.java @@ -4,14 +4,17 @@ import com.iab.openrtb.request.Audio; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Native; -import com.iab.openrtb.request.Site; import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.VertxTest; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; @@ -19,484 +22,484 @@ import org.prebid.server.bidder.model.HttpRequest; import org.prebid.server.bidder.model.HttpResponse; import org.prebid.server.bidder.model.Result; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalImp; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpMediaType; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpMediaTypes; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalImpZone; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalRequest; -import org.prebid.server.bidder.resetdigital.request.ResetDigitalSite; -import org.prebid.server.bidder.resetdigital.response.ResetDigitalBid; -import org.prebid.server.bidder.resetdigital.response.ResetDigitalResponse; -import org.prebid.server.proto.openrtb.ext.ExtPrebid; -import org.prebid.server.proto.openrtb.ext.request.resetdigital.ExtImpResetDigital; +import org.prebid.server.currency.CurrencyConversionService; +import org.prebid.server.exception.PreBidException; import java.math.BigDecimal; import java.util.List; -import java.util.Set; import java.util.function.UnaryOperator; -import java.util.stream.Stream; +import static java.util.Collections.singletonList; import static java.util.function.UnaryOperator.identity; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.AssertionsForClassTypes.tuple; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; import static org.prebid.server.proto.openrtb.ext.response.BidType.audio; import static org.prebid.server.proto.openrtb.ext.response.BidType.banner; import static org.prebid.server.proto.openrtb.ext.response.BidType.video; -import static org.prebid.server.util.HttpUtil.ACCEPT_HEADER; -import static org.prebid.server.util.HttpUtil.ACCEPT_LANGUAGE_HEADER; -import static org.prebid.server.util.HttpUtil.APPLICATION_JSON_CONTENT_TYPE; -import static org.prebid.server.util.HttpUtil.CONTENT_TYPE_HEADER; -import static org.prebid.server.util.HttpUtil.REFERER_HEADER; -import static org.prebid.server.util.HttpUtil.USER_AGENT_HEADER; -import static org.prebid.server.util.HttpUtil.X_FORWARDED_FOR_HEADER; -import static org.prebid.server.util.HttpUtil.X_REAL_IP_HEADER; -import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE; +@ExtendWith(MockitoExtension.class) public class ResetDigitalBidderTest extends VertxTest { public static final String ENDPOINT_URL = "https://test.endpoint.com"; + @Mock + private CurrencyConversionService currencyConversionService; + private ResetDigitalBidder target; @BeforeEach public void setUp() { - target = new ResetDigitalBidder(ENDPOINT_URL, jacksonMapper); + target = new ResetDigitalBidder(ENDPOINT_URL, currencyConversionService, jacksonMapper); } @Test public void creationShouldFailOnInvalidEndpointUrl() { assertThatIllegalArgumentException().isThrownBy(() -> - new ResetDigitalBidder("invalid_url", jacksonMapper)); + new ResetDigitalBidder("invalid_url", currencyConversionService, jacksonMapper)); } @Test - public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() { + public void makeHttpRequestShouldReturnEmptyResponseIfAbsentAnyTypeInImp() { // given - final BidRequest bidRequest = givenBidRequest( - imp -> imp.ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode())))); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(impBuilder -> impBuilder.banner(null)))) + .build(); // when - final Result>> result = target.makeHttpRequests(bidRequest); + final Result>> result = target.makeHttpRequests(bidRequest); // then - assertThat(result.getValue()).isEmpty(); - assertThat(result.getErrors()).hasSize(1).allSatisfy(bidderError -> { - assertThat(bidderError.getType()).isEqualTo(BidderError.Type.bad_input); - assertThat(bidderError.getMessage()).startsWith("Cannot deserialize value"); - }); + assertThat(result.getErrors()).hasSize(0); + assertThat(result.getValue()).hasSize(0); } @Test - public void makeHttpRequestsShouldMakeOneRequestPerImp() { + public void makeHttpRequestShouldReturnEmptyResponseIfxNativeImpTypePresent() { // given - final BidRequest bidRequest = givenBidRequest( - imp -> imp.id("givenImp1"), - imp -> imp.id("givenImp2"), - imp -> imp.id("givenImp3")); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(impBuilder -> impBuilder.banner(null) + .xNative(Native.builder().build())))) + .build(); - //when - final Result>> result = target.makeHttpRequests(bidRequest); + // when + final Result>> result = target.makeHttpRequests(bidRequest); - //then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(3) + // then + assertThat(result.getErrors()).hasSize(0); + assertThat(result.getValue()).hasSize(0); + } + + @Test + public void makeHttpRequestShouldReturnSeparateResponseWithBannerAndVideoAndAudioImp() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(impBuilder -> impBuilder + .audio(Audio.builder().build()) + .video(Video.builder().build())))) + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).hasSize(0); + assertThat(result.getValue()).hasSize(3); + assertThat(result.getValue().get(0)) .extracting(HttpRequest::getPayload) - .flatExtracting(ResetDigitalRequest::getImps) - .extracting(ResetDigitalImp::getImpId) - .containsExactlyInAnyOrder("givenImp1", "givenImp2", "givenImp3"); + .extracting(BidRequest::getImp) + .extracting(a -> a.getFirst()) + .extracting(Imp::getBanner) + .isNotNull(); - assertThat(result.getValue()).hasSize(3) - .extracting(HttpRequest::getImpIds) - .containsExactlyInAnyOrder(Set.of("givenImp1"), Set.of("givenImp2"), Set.of("givenImp3")); + assertThat(result.getValue().get(1)) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getImp) + .extracting(a -> a.getFirst()) + .extracting(Imp::getVideo) + .isNotNull(); + + assertThat(result.getValue().get(2)) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getImp) + .extracting(a -> a.getFirst()) + .extracting(Imp::getAudio) + .isNotNull(); } @Test - public void makeHttpRequestsShouldHaveCorrectUri() { + public void makeHttpRequestShouldReturnSeparateResponseWithBannerAndVideoImp() { // given - final BidRequest bidRequest = givenBidRequest(imp -> imp.id("givenImp")); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(impBuilder -> impBuilder + .video(Video.builder().build())))) + .build(); - //when - final Result>> result = target.makeHttpRequests(bidRequest); + // when + final Result>> result = target.makeHttpRequests(bidRequest); - //then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getUri) - .containsExactlyInAnyOrder(ENDPOINT_URL); + // then + assertThat(result.getErrors()).hasSize(0); + assertThat(result.getValue()).hasSize(2); + assertThat(result.getValue().get(0)) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getImp) + .extracting(a -> a.getFirst()) + .extracting(Imp::getBanner) + .isNotNull(); + + assertThat(result.getValue().get(1)) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getImp) + .extracting(a -> a.getFirst()) + .extracting(Imp::getVideo) + .isNotNull(); } @Test - public void makeHttpRequestsShouldReturnExpectedHeaders() { + public void makeHttpRequestShouldReturnSeparateResponseWithBannerAndAudioImp() { // given - final BidRequest bidRequest = givenBidRequest(identity()).toBuilder() - .device(Device.builder().ip("ip").ua("ua").language("lang").build()) - .site(Site.builder().page("page").build()) + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(impBuilder -> impBuilder + .audio(Audio.builder().build())))) .build(); // when - final Result>> result = target.makeHttpRequests(bidRequest); + final Result>> result = target.makeHttpRequests(bidRequest); // then - assertThat(result.getValue()).hasSize(1).first() - .extracting(HttpRequest::getHeaders) - .satisfies(headers -> { - assertThat(headers.get(CONTENT_TYPE_HEADER)).isEqualTo(APPLICATION_JSON_CONTENT_TYPE); - assertThat(headers.get(ACCEPT_HEADER)).isEqualTo(APPLICATION_JSON_VALUE); - assertThat(headers.get(USER_AGENT_HEADER)).isEqualTo("ua"); - assertThat(headers.get(ACCEPT_LANGUAGE_HEADER)).isEqualTo("lang"); - assertThat(headers.get(X_FORWARDED_FOR_HEADER)).isEqualTo("ip"); - assertThat(headers.get(X_REAL_IP_HEADER)).isEqualTo("ip"); - assertThat(headers.get(REFERER_HEADER)).isEqualTo("page"); - }); - assertThat(result.getErrors()).isEmpty(); + assertThat(result.getErrors()).hasSize(0); + assertThat(result.getValue()).hasSize(2); + assertThat(result.getValue().get(0)) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getImp) + .extracting(a -> a.getFirst()) + .extracting(Imp::getBanner) + .isNotNull(); + + assertThat(result.getValue().get(1)) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getImp) + .extracting(a -> a.getFirst()) + .extracting(Imp::getAudio) + .isNotNull(); } @Test - public void makeHttpRequestsShouldReturnExpectedHeadersWhenDeviceAndSiteAreNotPresent() { + public void makeHttpRequestShouldReturnSeparateResponseWithVideoAndAudioImp() { // given - final BidRequest bidRequest = givenBidRequest(identity()); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(impBuilder -> impBuilder + .banner(null) + .video(Video.builder().build()) + .audio(Audio.builder().build())))) + .build(); // when - final Result>> result = target.makeHttpRequests(bidRequest); + final Result>> result = target.makeHttpRequests(bidRequest); // then - assertThat(result.getValue()).hasSize(1).first() - .extracting(HttpRequest::getHeaders) - .satisfies(headers -> { - assertThat(headers.get(CONTENT_TYPE_HEADER)).isEqualTo(APPLICATION_JSON_CONTENT_TYPE); - assertThat(headers.get(ACCEPT_HEADER)).isEqualTo(APPLICATION_JSON_VALUE); - assertThat(headers.get(USER_AGENT_HEADER)).isNull(); - assertThat(headers.get(ACCEPT_LANGUAGE_HEADER)).isNull(); - assertThat(headers.get(X_FORWARDED_FOR_HEADER)).isNull(); - assertThat(headers.get(X_REAL_IP_HEADER)).isNull(); - assertThat(headers.get(REFERER_HEADER)).isNull(); - }); - assertThat(result.getErrors()).isEmpty(); + assertThat(result.getErrors()).hasSize(0); + assertThat(result.getValue()).hasSize(2); + assertThat(result.getValue().get(0)) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getImp) + .extracting(a -> a.getFirst()) + .extracting(Imp::getVideo) + .isNotNull(); + + assertThat(result.getValue().get(1)) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getImp) + .extracting(a -> a.getFirst()) + .extracting(Imp::getAudio) + .isNotNull(); } @Test - public void makeHttpRequestsShouldReturnBannerRequestFromBannerImp() { + public void makeHttpRequestShouldReturnResponseOnlyWithBannerImp() { // given - final BidRequest bidRequest = givenBidRequest(imp -> imp - .id("impId") - .banner(Banner.builder().w(1).h(2).build())) - .toBuilder() - .id("requestId") + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(identity()))) .build(); - //when - final Result>> result = target.makeHttpRequests(bidRequest); + // when + final Result>> result = target.makeHttpRequests(bidRequest); - //then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) + // then + assertThat(result.getErrors()).hasSize(0); + assertThat(result.getValue()) .extracting(HttpRequest::getPayload) - .flatExtracting(ResetDigitalRequest::getImps) - .containsExactlyInAnyOrder(ResetDigitalImp.builder() - .impId("impId") - .bidId("requestId") - .zoneId(ResetDigitalImpZone.of("placementId")) - .mediaTypes(ResetDigitalImpMediaTypes.banner(ResetDigitalImpMediaType.builder() - .sizes(List.of(List.of(1, 2))) - .build())) - .build()); + .flatExtracting(BidRequest::getImp) + .allSatisfy(imp -> { + assertThat(imp.getBanner()).isNotNull(); + assertThat(imp.getVideo()).isNull(); + assertThat(imp.getAudio()).isNull(); + }); } @Test - public void makeHttpRequestsShouldReturnVideoRequestFromVideoImp() { + public void makeHttpRequestShouldReturnResponseOnlyWithVideoImp() { // given - final BidRequest bidRequest = givenBidRequest(imp -> imp - .id("impId") - .banner(null) - .video(Video.builder().w(1).h(2).mimes(List.of("mime1", "mime2")).build())) - .toBuilder() - .id("requestId") + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(impBuilder -> impBuilder.banner(null) + .video(Video.builder().build())))) .build(); - //when - final Result>> result = target.makeHttpRequests(bidRequest); + // when + final Result>> result = target.makeHttpRequests(bidRequest); - //then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) + // then + assertThat(result.getErrors()).hasSize(0); + assertThat(result.getValue()) .extracting(HttpRequest::getPayload) - .flatExtracting(ResetDigitalRequest::getImps) - .containsExactlyInAnyOrder(ResetDigitalImp.builder() - .impId("impId") - .bidId("requestId") - .zoneId(ResetDigitalImpZone.of("placementId")) - .mediaTypes(ResetDigitalImpMediaTypes.video(ResetDigitalImpMediaType.builder() - .sizes(List.of(List.of(1, 2))) - .mimes(List.of("mime1", "mime2")) - .build())) - .build()); + .flatExtracting(BidRequest::getImp) + .allSatisfy(imp -> { + assertThat(imp.getBanner()).isNull(); + assertThat(imp.getVideo()).isNotNull(); + assertThat(imp.getAudio()).isNull(); + }); } @Test - public void makeHttpRequestsShouldReturnAudioRequestFromAudioImp() { + public void makeHttpRequestShouldReturnResponseOnlyWithAudioImp() { // given - final BidRequest bidRequest = givenBidRequest(imp -> imp - .id("impId") - .banner(null) - .audio(Audio.builder().mimes(List.of("mime1", "mime2")).build())) - .toBuilder() - .id("requestId") + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(impBuilder -> impBuilder.banner(null) + .audio(Audio.builder().build())))) .build(); - //when - final Result>> result = target.makeHttpRequests(bidRequest); + // when + final Result>> result = target.makeHttpRequests(bidRequest); - //then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) + // then + assertThat(result.getErrors()).hasSize(0); + assertThat(result.getValue()) .extracting(HttpRequest::getPayload) - .flatExtracting(ResetDigitalRequest::getImps) - .containsExactlyInAnyOrder(ResetDigitalImp.builder() - .impId("impId") - .bidId("requestId") - .zoneId(ResetDigitalImpZone.of("placementId")) - .mediaTypes(ResetDigitalImpMediaTypes.audio(ResetDigitalImpMediaType.builder() - .mimes(List.of("mime1", "mime2")) - .build())) - .build()); + .flatExtracting(BidRequest::getImp) + .allSatisfy(imp -> { + assertThat(imp.getBanner()).isNull(); + assertThat(imp.getVideo()).isNull(); + assertThat(imp.getAudio()).isNotNull(); + }); } @Test - public void makeHttpRequestsShouldReturnFailWhenImpIsNative() { + public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { // given - final BidRequest bidRequest = givenBidRequest(imp -> imp - .id("impId") - .banner(null) - .xNative(Native.builder().build())) - .toBuilder() - .id("requestId") - .build(); + final BidderCall httpCall = givenHttpCall(null, "invalid"); - //when - final Result>> result = target.makeHttpRequests(bidRequest); + // when + final Result> result = target.makeBids(httpCall, null); - //then + // then + assertThat(result.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token"); + }); assertThat(result.getValue()).isEmpty(); - assertThat(result.getErrors()).hasSize(1).allSatisfy(bidderError -> { - assertThat(bidderError.getType()).isEqualTo(BidderError.Type.bad_input); - assertThat(bidderError.getMessage()).isEqualTo("Banner, video or audio must be present in the imp impId"); - }); } @Test - public void makeHttpRequestsShouldReturnCorrectSite() { + public void makeHttpRequestsShouldConvertCurrencyIfRequestCurrencyDoesNotMatchBidderCurrency() { // given - final BidRequest bidRequest = givenBidRequest(identity()) - .toBuilder() - .site(Site.builder().domain("domain").page("page").build()) - .build(); + given(currencyConversionService.convertCurrency(any(), any(), anyString(), anyString())) + .willReturn(BigDecimal.TEN); - //when - final Result>> result = target.makeHttpRequests(bidRequest); + final BidRequest bidRequest = givenBidRequest( + impBuilder -> impBuilder.bidfloor(BigDecimal.ONE).bidfloorcur("EUR")); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); - //then + // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) + assertThat(result.getValue()) .extracting(HttpRequest::getPayload) - .flatExtracting(ResetDigitalRequest::getSite) - .containsExactlyInAnyOrder(ResetDigitalSite.builder() - .referrer("page") - .domain("domain") - .build()); + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getBidfloor, Imp::getBidfloorcur) + .containsOnly(tuple(BigDecimal.TEN, "USD")); } @Test - public void makeBidsShouldReturnErrorWhenResponseCanNotBeParsed() { + public void makeHttpRequestsShouldReturnErrorMessageOnFailedCurrencyConversion() { // given - final BidderCall httpCall = givenHttpCall("invalid"); + given(currencyConversionService.convertCurrency(any(), any(), anyString(), anyString())) + .willThrow(PreBidException.class); + + final BidRequest bidRequest = givenBidRequest( + impCustomizer -> impCustomizer.bidfloor(BigDecimal.ONE).bidfloorcur("EUR")); // when - final Result> actual = target.makeBids(httpCall, null); + final Result>> result = target.makeHttpRequests(bidRequest); // then - assertThat(actual.getValue()).isEmpty(); - assertThat(actual.getErrors()).hasSize(1) - .allSatisfy(error -> { - assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token 'invalid':"); - assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); - }); + assertThat(result.getErrors()).allSatisfy(bidderError -> { + assertThat(bidderError.getType()) + .isEqualTo(BidderError.Type.bad_input); + assertThat(bidderError.getMessage()) + .isEqualTo("Unable to convert provided bid floor currency from EUR to USD for imp `123`"); + }); } @Test - public void makeBidsShouldReturnEmptyBidsWhenResponseDoesNotHaveBids() throws JsonProcessingException { + public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall(givenBidResponse()); + final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString(null)); // when - final Result> actual = target.makeBids(httpCall, null); + final Result> result = target.makeBids(httpCall, null); // then - assertThat(actual.getValue()).isEmpty(); - assertThat(actual.getErrors()) - .containsOnly(BidderError.badServerResponse("expected exactly one bid in the response, but got 0")); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); } @Test - public void makeBidsShouldReturnEmptyBidsWhenResponseHasMoreThanOneBid() throws JsonProcessingException { + public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall(givenBidResponse(identity(), identity())); + final BidderCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(BidResponse.builder().build())); // when - final Result> actual = target.makeBids(httpCall, null); + final Result> result = target.makeBids(httpCall, null); // then - assertThat(actual.getValue()).isEmpty(); - assertThat(actual.getErrors()) - .containsOnly(BidderError.badServerResponse("expected exactly one bid in the response, but got 2")); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); } @Test - public void makeBidsShouldReturnEmptyBidsWhenResponseDoesNotHaveBidThatMatchesAnyImp() - throws JsonProcessingException { - + public void makeBidsShouldReturnBannerBidIfBannerIsPresentInRequestImp() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall(givenBidResponse(bid -> bid.impId("impId1"))); + final BidderCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").banner(Banner.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); // when - final Result> actual = target.makeBids(httpCall, givenBidRequest(imp -> imp.id("impId2"))); + final Result> result = target.makeBids(httpCall, null); // then - assertThat(actual.getValue()).isEmpty(); - assertThat(actual.getErrors()) - .containsOnly(BidderError.badServerResponse("no matching impression found for ImpID impId1")); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); } @Test - public void makeBidsShouldReturnBannerBidSuccessfully() throws JsonProcessingException { + public void makeBidsShouldReturnVideoBidIfVideoIsPresentInRequestImp() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall(givenBidResponse(bid -> bid - .cpm(BigDecimal.TEN) - .cid("cid") - .html("html") - .crid("crid") - .seat("seat") - .impId("impId") - .bidId("bidId") - .w("1") - .h("2"))); + final BidderCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").video(Video.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); // when - final Result> result = target.makeBids( - httpCall, - givenBidRequest(imp -> imp.id("impId").banner(Banner.builder().build()))); + final Result> result = target.makeBids(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - final Bid expectedBid = Bid.builder() - .adm("html") - .price(BigDecimal.TEN) - .cid("cid") - .w(1) - .h(2) - .impid("impId") - .id("bidId") - .crid("crid") - .build(); - assertThat(result.getValue()).containsExactly(BidderBid.of(expectedBid, banner, "seat", "USD")); + assertThat(result.getValue()) + .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), video, "USD")); } @Test - public void makeBidsShouldReturnVideoBidSuccessfully() throws JsonProcessingException { + public void makeBidsShouldReturnAudioBidIfAudioIsPresentInRequestImp() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall(givenBidResponse(bid -> bid - .cpm(BigDecimal.TEN) - .cid("cid") - .html("html") - .crid("crid") - .seat("seat") - .impId("impId") - .bidId("bidId") - .w("1") - .h("2"))); + final BidderCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").audio(Audio.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); // when - final Result> result = target.makeBids( - httpCall, - givenBidRequest(imp -> imp.id("impId").video(Video.builder().build()))); + final Result> result = target.makeBids(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - final Bid expectedBid = Bid.builder() - .adm("html") - .price(BigDecimal.TEN) - .cid("cid") - .w(1) - .h(2) - .impid("impId") - .id("bidId") - .crid("crid") - .build(); - assertThat(result.getValue()).containsExactly(BidderBid.of(expectedBid, video, "seat", "USD")); + assertThat(result.getValue()) + .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), audio, "USD")); } @Test - public void makeBidsShouldReturnAudioBidSuccessfully() throws JsonProcessingException { + public void makeBidsShouldReturnErrorBidIfBidTypeIsAbsentInRequestImp() throws JsonProcessingException { // given - final BidderCall httpCall = givenHttpCall(givenBidResponse(bid -> bid - .cpm(BigDecimal.TEN) - .cid("cid") - .html("html") - .crid("crid") - .seat("seat") - .impId("impId") - .bidId("bidId") - .w("1") - .h("2"))); + final BidderCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); // when - final Result> result = target.makeBids( - httpCall, - givenBidRequest(imp -> imp.id("impId").audio(Audio.builder().build()))); + final Result> result = target.makeBids(httpCall, null); // then - assertThat(result.getErrors()).isEmpty(); - final Bid expectedBid = Bid.builder() - .adm("html") - .price(BigDecimal.TEN) - .cid("cid") - .w(1) - .h(2) - .impid("impId") - .id("bidId") - .crid("crid") - .build(); - assertThat(result.getValue()).containsExactly(BidderBid.of(expectedBid, audio, "seat", "USD")); + assertThat(result.getErrors()).hasSize(1) + .extracting(BidderError::getMessage) + .containsExactly("Failed to find banner/video/audio impression 123"); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnErrorIfBidCurIsNotUsd() throws JsonProcessingException { + // given + final BidderCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(identity()).toBuilder().cur("EUR").build())); + + // when + final Result> result = target.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).hasSize(1) + .extracting(BidderError::getMessage) + .containsExactly("Bidder support only USD currency"); + assertThat(result.getValue()).isEmpty(); } - private static BidRequest givenBidRequest(UnaryOperator... impCustomizers) { - return BidRequest.builder() - .imp(Stream.of(impCustomizers).map(ResetDigitalBidderTest::givenImp).toList()) + private static BidRequest givenBidRequest(UnaryOperator bidRequestCustomizer, + UnaryOperator impCustomizer) { + + return bidRequestCustomizer.apply(BidRequest.builder() + .imp(singletonList(givenImp(impCustomizer)))) .build(); } + private static BidRequest givenBidRequest(UnaryOperator impCustomizer) { + return givenBidRequest(identity(), impCustomizer); + } + private static Imp givenImp(UnaryOperator impCustomizer) { return impCustomizer.apply(Imp.builder() - .id("impId") - .banner(Banner.builder().w(23).h(25).build()) - .ext(mapper.valueToTree(ExtPrebid.of( - null, - ExtImpResetDigital.of("placementId"))))) + .id("123") + .banner(Banner.builder().w(23).h(25).build())) .build(); } - private static BidderCall givenHttpCall(String body) { + private static BidResponse givenBidResponse(UnaryOperator bidCustomizer) { + return BidResponse.builder() + .seatbid(singletonList(SeatBid.builder().bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .build())) + .cur("USD") + .build(); + } + + private static BidderCall givenHttpCall(BidRequest bidRequest, String body) { return BidderCall.succeededHttp( - HttpRequest.builder().payload(null).build(), + HttpRequest.builder().payload(bidRequest).build(), HttpResponse.of(200, null, body), null); } - - private String givenBidResponse(UnaryOperator... bidCustomizers) - throws JsonProcessingException { - - return mapper.writeValueAsString(ResetDigitalResponse.of( - Stream.of(bidCustomizers) - .map(bidCustomizer -> bidCustomizer.apply(ResetDigitalBid.builder()).build()) - .toList())); - } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-request.json b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-request.json index 9fffce432ec..9ee75999128 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-request.json @@ -1,31 +1,20 @@ { - "id": "12345", + "id": "request_id", "imp": [ { - "id": "001", + "id": "imp_id", "banner": { - "h": 300, - "w": 250 + "w": 300, + "h": 250 }, "ext": { "resetdigital": { - "placement_id": "placement-id-1" + "pubId": "lb.ads", + "zoneId": "publisherTestID" } } } ], - "site": { - "domain": "https://test.com", - "page": "https://test.com/2016/06/12" - }, - "cur": [ - "USD" - ], - "device": { - "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36", - "ip": "127.0.0.1", - "language": "EN" - }, "tmax": 5000, "regs": { "ext": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-response.json index 53308c326ee..556bc6d3217 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-auction-resetdigital-response.json @@ -1,18 +1,19 @@ { - "id": "12345", + "id": "request_id", "seatbid": [ { "bid": [ { - "adm": "test markup", - "cid": "1002088", - "crid": "1000763-1002088", - "id": "01", - "impid": "001", - "price": 1.00, + "id": "bid_id", + "impid": "imp_id", + "exp": 300, + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", "w": 300, "h": 250, - "exp": 300, "ext": { "prebid": { "type": "banner", @@ -20,7 +21,7 @@ "adaptercode": "resetdigital" } }, - "origbidcpm": 1.00, + "origbidcpm": 3.33, "origbidcur": "USD" } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-request.json index 3b12e3d3c8a..43d9d50841b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-request.json @@ -1,25 +1,57 @@ { - "imps": [ + "id": "request_id", + "imp": [ { - "bid_id": "12345", - "imp_id": "001", - "media_types": { - "banner": { - "sizes": [ - [ - 250, - 300 - ] - ] - } + "id": "imp_id", + "secure": 1, + "banner": { + "w": 300, + "h": 250 }, - "zone_id": { - "placementId": "placement-id-1" + "ext": { + "tid": "${json-unit.any-string}", + "bidder": { + "pubId": "lb.ads", + "zoneId": "publisherTestID" + } } } ], + "source": { + "tid": "${json-unit.any-string}" + }, "site": { - "domain": "https://test.com", - "referrer": "https://test.com/2016/06/12" + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "domain": "example.com" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "193.168.244.1" + }, + "at": 1, + "tmax": "${json-unit.any-number}", + "cur": [ + "USD" + ], + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "server": { + "externalurl": "http://localhost:8080", + "gvlid": 1, + "datacenter": "local", + "endpoint": "/openrtb2/auction" + } + } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-response.json index 3397880777f..631464ca55d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/resetdigital/test-resetdigital-bid-response.json @@ -1,16 +1,21 @@ { - "bids": [ + "id": "request_id", + "seatbid": [ { - "bid_id": "01", - "imp_id": "001", - "cpm": 1.00, - "cid": "1002088", - "crid": "1000763-1002088", - "adid": "1002088", - "w": "300", - "h": "250", - "seat": "resetdigital", - "html": "test markup" + "bid": [ + { + "id": "bid_id", + "impid": "imp_id", + "price": 3.33, + "adid": "adid001", + "crid": "crid001", + "cid": "cid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] } - ] + ], + "cur": "USD" } From 888dfc2d43debbd3eecb269a31dff7850839fae8 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 13 Mar 2025 16:28:17 +0100 Subject: [PATCH 16/23] Fix targeting --- .../server/auction/BidResponseCreator.java | 12 +- .../server/auction/model/TargetingInfo.java | 2 + .../auction/BidResponseCreatorTest.java | 157 +++++++++--------- 3 files changed, 91 insertions(+), 80 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 642ff12c5fd..1623ab53070 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -775,12 +775,18 @@ private static List injectTargeting(List bidderImpIdBidInfos, : bidderCodePrefix == null ? null : bidderCodePrefix + (i + 1); final BidInfo bidInfo = bidderImpIdBidInfos.get(i); + + final String targetingSeat = isFirstBid + ? bidInfo.getSeat() + : bidderCodePrefix == null ? null : bidderCodePrefix + (i + 1); + final TargetingInfo targetingInfo = TargetingInfo.builder() .isTargetingEnabled(targetingBidderCode != null) .isBidderWinningBid(winningBidsByBidder.contains(bidInfo)) .isWinningBid(winningBids.contains(bidInfo)) .isAddTargetBidderCode(targetingBidderCode != null && multiBidSize > 1) .bidderCode(targetingBidderCode) + .seat(targetingSeat) .build(); final BidInfo modifiedBidInfo = bidInfo.toBuilder().targetingInfo(targetingInfo).build(); @@ -1520,16 +1526,16 @@ private Bid toBid(BidInfo bidInfo, final String videoCacheId = cacheInfo != null ? cacheInfo.getVideoCacheId() : null; final Map targetingKeywords; - final String bidderCode = targetingInfo.getBidderCode(); if (shouldIncludeTargetingInResponse(targeting, bidInfo.getTargetingInfo())) { final TargetingKeywordsCreator keywordsCreator = resolveKeywordsCreator( bidType, targeting, bidRequest, account, bidWarnings); final boolean isWinningBid = targetingInfo.isWinningBid(); + final String seat = targetingInfo.getSeat(); final String categoryDuration = bidInfo.getCategory(); targetingKeywords = keywordsCreator != null ? keywordsCreator.makeFor( - bid, bidderCode, isWinningBid, cacheId, bidType.getName(), videoCacheId, categoryDuration) + bid, seat, isWinningBid, cacheId, bidType.getName(), videoCacheId, categoryDuration) : null; } else { targetingKeywords = null; @@ -1547,7 +1553,7 @@ private Bid toBid(BidInfo bidInfo, .map(ExtBidPrebid::toBuilder) .orElseGet(ExtBidPrebid::builder) .targeting(MapUtils.isNotEmpty(targetingKeywords) ? targetingKeywords : null) - .targetBidderCode(targetingInfo.isAddTargetBidderCode() ? bidderCode : null) + .targetBidderCode(targetingInfo.isAddTargetBidderCode() ? targetingInfo.getBidderCode() : null) .dealTierSatisfied(dealsTierSatisfied) .cache(cache) .passThrough(extractPassThrough(bidInfo.getCorrespondingImp())) diff --git a/src/main/java/org/prebid/server/auction/model/TargetingInfo.java b/src/main/java/org/prebid/server/auction/model/TargetingInfo.java index a85b1041971..dbd3d7fd2b3 100644 --- a/src/main/java/org/prebid/server/auction/model/TargetingInfo.java +++ b/src/main/java/org/prebid/server/auction/model/TargetingInfo.java @@ -9,6 +9,8 @@ public class TargetingInfo { String bidderCode; + String seat; + boolean isTargetingEnabled; boolean isWinningBid; diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index 07d695d0989..482a85b8c46 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -1591,11 +1591,11 @@ public void shouldPopulateTargetingKeywords() { .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.00"), - tuple("hb_pb_bidder1", "5.00"), - tuple("hb_bidder", "bidder1"), - tuple("hb_bidder_bidder1", "bidder1"), + tuple("hb_pb_seat", "5.00"), + tuple("hb_bidder", "seat"), + tuple("hb_bidder_seat", "seat"), tuple("hb_env", "mobile-app"), - tuple("hb_env_bidder1", "mobile-app")); + tuple("hb_env_seat", "mobile-app")); verify(coreCacheService, never()).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -1627,11 +1627,11 @@ public void shouldPopulateTargetingKeywordsForAmpRequest() { .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.00"), - tuple("hb_pb_bidder1", "5.00"), - tuple("hb_bidder", "bidder1"), - tuple("hb_bidder_bidder1", "bidder1"), + tuple("hb_pb_seat", "5.00"), + tuple("hb_bidder", "seat"), + tuple("hb_bidder_seat", "seat"), tuple("hb_env", "amp"), - tuple("hb_env_bidder1", "amp")); + tuple("hb_env_seat", "amp")); verify(coreCacheService, never()).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -1641,7 +1641,7 @@ public void shouldTruncateTargetingKeywordsByGlobalConfig() { // given final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("someVeryLongBidderName", - givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "someVeryLongSeatName", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1679,10 +1679,10 @@ public void shouldTruncateTargetingKeywordsByGlobalConfig() { .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.00"), - tuple("hb_pb_someVeryLongBi", "5.00"), - tuple("hb_bidder", "someVeryLongBidderName"), - tuple("hb_bidder_someVeryLo", "someVeryLongBidderName"), - tuple("hb_bidder_someVeryLo", "someVeryLongBidderName")); + tuple("hb_pb_someVeryLongSe", "5.00"), + tuple("hb_bidder", "someVeryLongSeatName"), + tuple("hb_bidder_someVeryLo", "someVeryLongSeatName"), + tuple("hb_bidder_someVeryLo", "someVeryLongSeatName")); } @Test @@ -1701,7 +1701,7 @@ public void shouldTruncateTargetingKeywordsByAccountConfig() { final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("someVeryLongBidderName", - givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "someVeryLongSeatName", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -1720,9 +1720,9 @@ public void shouldTruncateTargetingKeywordsByAccountConfig() { .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.00"), - tuple("hb_pb_someVeryLongBi", "5.00"), - tuple("hb_bidder", "someVeryLongBidderName"), - tuple("hb_bidder_someVeryLo", "someVeryLongBidderName")); + tuple("hb_pb_someVeryLongSe", "5.00"), + tuple("hb_bidder", "someVeryLongSeatName"), + tuple("hb_bidder_someVeryLo", "someVeryLongSeatName")); } @Test @@ -1750,7 +1750,7 @@ public void shouldTruncateTargetingKeywordsByRequestPassedValue() { final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("someVeryLongBidderName", - givenSeatBid(BidderBid.of(bid, banner, "seat", "USD")), 100)); + givenSeatBid(BidderBid.of(bid, banner, "someVeryLongSeatName", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -1769,15 +1769,16 @@ public void shouldTruncateTargetingKeywordsByRequestPassedValue() { .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.00"), - tuple("hb_pb_someVeryLongBi", "5.00"), - tuple("hb_bidder", "someVeryLongBidderName"), - tuple("hb_bidder_someVeryLo", "someVeryLongBidderName")); + tuple("hb_pb_someVeryLongSe", "5.00"), + tuple("hb_bidder", "someVeryLongSeatName"), + tuple("hb_bidder_someVeryLo", "someVeryLongSeatName")); } @Test public void shouldReduceAndNotPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIsNotDefined() { // given final String bidder1 = "bidder1"; + final String seat = "seat"; final Map multiBidMap = singletonMap(bidder1, MultiBidConfig.of(bidder1, 3, null)); final Bid bidder1Bid1 = Bid.builder().id("bidder1Bid1").price(BigDecimal.valueOf(3.67)).impid("i1").build(); @@ -1789,11 +1790,11 @@ public void shouldReduceAndNotPopulateTargetingKeywordsForExtraBidsWhenCodePrefi final List bidderResponses = singletonList( BidderResponse.of(bidder1, givenSeatBid( - BidderBid.of(bidder1Bid1, banner, "seat", null), // extra bid - BidderBid.of(bidder1Bid2, banner, "seat", null), // extra bid - BidderBid.of(bidder1Bid3, banner, "seat", null), // Will be removed by price - BidderBid.of(bidder1Bid4, banner, "seat", null), - BidderBid.of(bidder1Bid5, banner, "seat", null)), + BidderBid.of(bidder1Bid1, banner, seat, null), // extra bid + BidderBid.of(bidder1Bid2, banner, seat, null), // extra bid + BidderBid.of(bidder1Bid3, banner, seat, null), // Will be removed by price + BidderBid.of(bidder1Bid4, banner, seat, null), + BidderBid.of(bidder1Bid5, banner, seat, null)), 100)); final AuctionContext auctionContext = givenAuctionContext( @@ -1812,13 +1813,13 @@ public void shouldReduceAndNotPopulateTargetingKeywordsForExtraBidsWhenCodePrefi .extracting( Bid::getId, bid -> toTargetingByKey(bid, "hb_bidder"), - bid -> toTargetingByKey(bid, "hb_bidder_bidder1"), + bid -> toTargetingByKey(bid, "hb_bidder_seat"), BidResponseCreatorTest::getTargetingBidderCode) .containsOnly( - tuple("bidder1Bid4", bidder1, bidder1, bidder1), + tuple("bidder1Bid4", seat, seat, bidder1), tuple("bidder1Bid2", null, null, null), tuple("bidder1Bid1", null, null, null), - tuple("bidder1Bid5", bidder1, bidder1, null)); + tuple("bidder1Bid5", seat, seat, null)); verify(coreCacheService, never()).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -1862,7 +1863,7 @@ public void shouldNotPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIsDefine final Map expectedWinningBidTargetingMap = new HashMap<>(); expectedWinningBidTargetingMap.put("hb_pb", "4.50"); - expectedWinningBidTargetingMap.put("hb_bidder", bidder1); + expectedWinningBidTargetingMap.put("hb_bidder", "seat"); // then assertThat(result.getSeatbid()) @@ -1880,6 +1881,7 @@ public void shouldNotPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIsDefine public void shouldReduceAndPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIsDefined() { // given final String bidder1 = "bidder1"; + final String seat = "seat"; final String codePrefix = "bN"; final Map multiBidMap = singletonMap(bidder1, MultiBidConfig.of(bidder1, 3, codePrefix)); @@ -1893,11 +1895,11 @@ public void shouldReduceAndPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIs final List bidderResponses = singletonList( BidderResponse.of(bidder1, givenSeatBid( - BidderBid.of(bidder1Bid1, banner, "seat", null), // extra bid - BidderBid.of(bidder1Bid2, banner, "seat", null), // extra bid - BidderBid.of(bidder1Bid3, banner, "seat", null), // Will be removed by price - BidderBid.of(bidder1Bid4, banner, "seat", null), - BidderBid.of(bidder1Bid5, banner, "seat", null)), + BidderBid.of(bidder1Bid1, banner, seat, null), // extra bid + BidderBid.of(bidder1Bid2, banner, seat, null), // extra bid + BidderBid.of(bidder1Bid3, banner, seat, null), // Will be removed by price + BidderBid.of(bidder1Bid4, banner, seat, null), + BidderBid.of(bidder1Bid5, banner, seat, null)), 100)); final AuctionContext auctionContext = givenAuctionContext( @@ -1913,9 +1915,9 @@ public void shouldReduceAndPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIs // then final Map bidder1Bid4Targeting = new HashMap<>(); bidder1Bid4Targeting.put("hb_pb", "5.00"); - bidder1Bid4Targeting.put("hb_pb_" + bidder1, "5.00"); - bidder1Bid4Targeting.put("hb_bidder_" + bidder1, bidder1); - bidder1Bid4Targeting.put("hb_bidder", bidder1); + bidder1Bid4Targeting.put("hb_pb_" + seat, "5.00"); + bidder1Bid4Targeting.put("hb_bidder_" + seat, seat); + bidder1Bid4Targeting.put("hb_bidder", seat); final ObjectNode bidder1Bid4Ext = extWithTargeting(bidder1, bidder1Bid4Targeting); final Bid expectedBidder1Bid4 = bidder1Bid4.toBuilder().ext(bidder1Bid4Ext).build(); @@ -1935,9 +1937,9 @@ public void shouldReduceAndPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIs final Map bidder1Bid5Targeting = new HashMap<>(); bidder1Bid5Targeting.put("hb_pb", "1.00"); - bidder1Bid5Targeting.put("hb_pb_" + bidder1, "1.00"); - bidder1Bid5Targeting.put("hb_bidder_" + bidder1, bidder1); - bidder1Bid5Targeting.put("hb_bidder", bidder1); + bidder1Bid5Targeting.put("hb_pb_" + seat, "1.00"); + bidder1Bid5Targeting.put("hb_bidder_" + seat, seat); + bidder1Bid5Targeting.put("hb_bidder", seat); final ObjectNode bidder1Bid5Ext = extWithTargeting(null, bidder1Bid5Targeting); final Bid expectedBidder1Bid5 = bidder1Bid5.toBuilder().ext(bidder1Bid5Ext).build(); @@ -1956,10 +1958,10 @@ public void shouldPopulateTargetingKeywordsForWinningBidsAndWinningBidsByBidder( final List bidderResponses = asList( BidderResponse.of("bidder1", givenSeatBid( - BidderBid.of(firstBid, banner, "seat", null), - BidderBid.of(secondBid, banner, "seat", null)), 100), + BidderBid.of(firstBid, banner, "seat1", null), + BidderBid.of(secondBid, banner, "seat1", null)), 100), BidderResponse.of("bidder2", - givenSeatBid(BidderBid.of(thirdBid, banner, "seat", null)), 111)); + givenSeatBid(BidderBid.of(thirdBid, banner, "seat2", null)), 111)); final AuctionContext auctionContext = givenAuctionContext( givenBidRequest( @@ -1977,12 +1979,12 @@ public void shouldPopulateTargetingKeywordsForWinningBidsAndWinningBidsByBidder( .extracting( Bid::getId, bid -> toTargetingByKey(bid, "hb_bidder"), - bid -> toTargetingByKey(bid, "hb_bidder_bidder1"), - bid -> toTargetingByKey(bid, "hb_bidder_bidder2")) + bid -> toTargetingByKey(bid, "hb_bidder_seat1"), + bid -> toTargetingByKey(bid, "hb_bidder_seat2")) .containsOnly( - tuple("bidId1", "bidder1", "bidder1", null), - tuple("bidId2", null, "bidder1", null), - tuple("bidId3", "bidder2", null, "bidder2")); + tuple("bidId1", "seat1", "seat1", null), + tuple("bidId2", null, "seat1", null), + tuple("bidId3", "seat2", null, "seat2")); verify(coreCacheService, never()).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -2030,9 +2032,9 @@ public void shouldPopulateTargetingKeywordsFromMediaTypePriceGranularities() { .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.000"), - tuple("hb_bidder", "bidder1"), - tuple("hb_pb_bidder1", "5.000"), - tuple("hb_bidder_bidder1", "bidder1")); + tuple("hb_bidder", "seat"), + tuple("hb_pb_seat", "5.000"), + tuple("hb_bidder_seat", "seat")); verify(coreCacheService, never()).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -2066,17 +2068,17 @@ public void shouldPopulateCacheIdHostPathAndUuidTargetingKeywords() { .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.00"), - tuple("hb_bidder", "bidder1"), + tuple("hb_bidder", "seat"), tuple("hb_cache_id", "cacheId"), tuple("hb_uuid", "videoId"), tuple("hb_cache_host", "testHost"), tuple("hb_cache_path", "testPath"), - tuple("hb_pb_bidder1", "5.00"), - tuple("hb_bidder_bidder1", "bidder1"), - tuple("hb_cache_id_bidder1", "cacheId"), - tuple("hb_uuid_bidder1", "videoId"), - tuple("hb_cache_host_bidder1", "testHost"), - tuple("hb_cache_path_bidder1", "testPath")); + tuple("hb_pb_seat", "5.00"), + tuple("hb_bidder_seat", "seat"), + tuple("hb_cache_id_seat", "cacheId"), + tuple("hb_uuid_seat", "videoId"), + tuple("hb_cache_host_seat", "testHost"), + tuple("hb_cache_path_seat", "testPath")); verify(coreCacheService).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -2550,9 +2552,9 @@ public void shouldNotPopulateWinningBidTargetingIfIncludeWinnersFlagIsFalse() { .extracting( Bid::getId, extractedBid -> toTargetingByKey(extractedBid, "hb_bidder"), - extractedBid -> toTargetingByKey(extractedBid, "hb_bidder_bidder1")) + extractedBid -> toTargetingByKey(extractedBid, "hb_bidder_seat")) .containsOnly( - tuple("bidId", null, "bidder1")); + tuple("bidId", null, "seat")); verify(coreCacheService).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -2596,9 +2598,9 @@ public void shouldNotPopulateBidderKeysTargetingIfIncludeBidderKeysFlagIsFalse() .extracting( Bid::getId, extractedBid -> toTargetingByKey(extractedBid, "hb_bidder"), - extractedBid -> toTargetingByKey(extractedBid, "hb_bidder_bidder1")) + extractedBid -> toTargetingByKey(extractedBid, "hb_bidder_seat")) .containsOnly( - tuple("bidId", "bidder1", null)); + tuple("bidId", "seat", null)); verify(coreCacheService).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -2615,8 +2617,8 @@ public void shouldNotPopulateCacheIdTargetingKeywordsIfBidCpmIsZero() { final Bid secondBid = Bid.builder().id("bidId2").impid("impId2").price(BigDecimal.valueOf(5.67)).build(); final List bidderResponses = asList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(firstBid, banner, "seat", null)), 99), - BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(secondBid, banner, "seat", null)), 123)); + BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(firstBid, banner, "seat1", null)), 99), + BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(secondBid, banner, "seat2", null)), 123)); final AuctionContext auctionContext = givenAuctionContext( bidRequest, @@ -2634,10 +2636,10 @@ public void shouldNotPopulateCacheIdTargetingKeywordsIfBidCpmIsZero() { .extracting( bid -> toTargetingByKey(bid, "hb_bidder"), bid -> toTargetingByKey(bid, "hb_cache_id"), - bid -> toTargetingByKey(bid, "hb_cache_id_bidder2")) + bid -> toTargetingByKey(bid, "hb_cache_id_seat2")) .containsOnly( - tuple("bidder1", null, null), - tuple("bidder2", "cacheId2", "cacheId2")); + tuple("seat1", null, null), + tuple("seat2", "cacheId2", "cacheId2")); verify(coreCacheService).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -4129,9 +4131,9 @@ public void shouldPopulateBidExtWhenExtMediaTypePriceGranularityHasValidVideoExt .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.00"), - tuple("hb_bidder", "bidder1"), - tuple("hb_pb_bidder1", "5.00"), - tuple("hb_bidder_bidder1", "bidder1")); + tuple("hb_bidder", "seat"), + tuple("hb_pb_seat", "5.00"), + tuple("hb_bidder_seat", "seat")); } @Test @@ -4172,9 +4174,9 @@ public void shouldPopulateBidExtWhenExtMediaTypePriceGranularityHasValidxNativeE .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.00"), - tuple("hb_bidder", "bidder1"), - tuple("hb_pb_bidder1", "5.00"), - tuple("hb_bidder_bidder1", "bidder1")); + tuple("hb_bidder", "seat"), + tuple("hb_pb_seat", "5.00"), + tuple("hb_bidder_seat", "seat")); } @Test @@ -4243,9 +4245,9 @@ public void shouldPopulateTargetingKeywordsWithDefaultPrefixAndRelatedWarning() .extracting(Map.Entry::getKey, Map.Entry::getValue) .containsOnly( tuple("hb_pb", "5.00"), - tuple("hb_pb_bidder1", "5.00"), - tuple("hb_bidder", "bidder1"), - tuple("hb_bidder_bidder1", "bidder1")); + tuple("hb_pb_seat", "5.00"), + tuple("hb_bidder", "seat"), + tuple("hb_bidder_seat", "seat")); final String expectedErrorMsg = "Key prefix value is dropped to default. " + "Decrease custom prefix length or increase truncateattrchars by 30"; @@ -5367,6 +5369,7 @@ private static BidInfo toBidInfo(Bid bid, .bidType(bidType) .targetingInfo(TargetingInfo.builder() .bidderCode(bidder) + .seat(seat) .isTargetingEnabled(true) .isWinningBid(isWinningBid) .isBidderWinningBid(true) From 3aa54413787c69e3844290cc4c03b598b7c97b01 Mon Sep 17 00:00:00 2001 From: osulzhenko Date: Mon, 17 Mar 2025 17:36:20 +0200 Subject: [PATCH 17/23] Fix NPE for stored response --- .../org/prebid/server/auction/StoredResponseProcessor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java b/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java index 1f5b0d83258..2257320ef69 100644 --- a/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java +++ b/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java @@ -428,7 +428,7 @@ private BidderSeatBid makeBidderSeatBid(BidderSeatBid bidderSeatBid, : DEFAULT_BID_CURRENCY; final List bidderBids = seatBid != null ? seatBid.getBid().stream() - .map(bid -> makeBidderBid(bid, bidCurrency, impIdToBidType)) + .map(bid -> makeBidderBid(bid, bidCurrency, seatBid.getSeat(), impIdToBidType)) .collect(Collectors.toCollection(ArrayList::new)) : new ArrayList<>(); if (nonNullBidderSeatBid) { @@ -439,8 +439,8 @@ private BidderSeatBid makeBidderSeatBid(BidderSeatBid bidderSeatBid, : BidderSeatBid.of(bidderBids); } - private BidderBid makeBidderBid(Bid bid, String bidCurrency, Map impIdToBidType) { - return BidderBid.of(bid, getBidType(bid.getExt(), impIdToBidType.get(bid.getImpid())), bidCurrency); + private BidderBid makeBidderBid(Bid bid, String bidCurrency, String seat, Map impIdToBidType) { + return BidderBid.of(bid, getBidType(bid.getExt(), impIdToBidType.get(bid.getImpid())), seat, bidCurrency); } private BidType getBidType(ObjectNode bidExt, BidType bidType) { From d579a85ca71b87159a8d59ebd71e95870acfb2d9 Mon Sep 17 00:00:00 2001 From: osulzhenko Date: Mon, 17 Mar 2025 18:58:55 +0200 Subject: [PATCH 18/23] Update unit tests --- .../auction/StoredResponseProcessorTest.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/test/java/org/prebid/server/auction/StoredResponseProcessorTest.java b/src/test/java/org/prebid/server/auction/StoredResponseProcessorTest.java index a137578ef14..dc57b3c1f11 100644 --- a/src/test/java/org/prebid/server/auction/StoredResponseProcessorTest.java +++ b/src/test/java/org/prebid/server/auction/StoredResponseProcessorTest.java @@ -530,7 +530,8 @@ public void mergeWithBidderResponsesShouldReturnMergedStoredSeatWithResponseWith // given final BidderResponse bidderResponse = BidderResponse.of( "rubicon", - BidderSeatBid.of(singletonList(BidderBid.of(Bid.builder().id("bid1").build(), BidType.banner, "USD"))), + BidderSeatBid.of(singletonList(BidderBid.of( + Bid.builder().id("bid1").build(), BidType.banner, "rubicon", "USD"))), 100); final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() .bidder("rubicon") @@ -566,12 +567,14 @@ public void mergeWithBidderResponsesShouldReturnMergedStoredSeatWithResponseWith .impid("storedImp") .build(), BidType.banner, + "rubicon", "USD"), BidderBid.of( Bid.builder() .id("bid1") .build(), BidType.banner, + "rubicon", "USD")); verifyNoInteractions(appnexusBidRejectionTracker); @@ -611,7 +614,7 @@ public void mergeWithBidderResponsesShouldMergeBidderResponsesWithoutCorrespondi // then final List expectedAppnexusBids = singletonList( - BidderBid.of(Bid.builder().id("bid2").impid("storedImp").build(), BidType.banner, "USD")); + BidderBid.of(Bid.builder().id("bid2").impid("storedImp").build(), BidType.banner, "appnexus", "USD")); verify(rubiconBidRejectionTracker).restoreFromRejection(givenRubiconBids); verify(appnexusBidRejectionTracker).restoreFromRejection(expectedAppnexusBids); @@ -647,6 +650,7 @@ public void mergeWithBidderResponsesShouldMergeStoredSeatBidsWithoutBidderRespon final List expectedBids = singletonList(BidderBid.of( Bid.builder().id("bid2").impid("storedImp").build(), BidType.banner, + "rubicon", "USD")); verify(rubiconBidRejectionTracker).restoreFromRejection(expectedBids); @@ -663,7 +667,8 @@ public void mergeWithBidderResponsesShouldResolveCurrencyFromBidderResponse() { final BidderResponse bidderResponse = BidderResponse.of( "rubicon", BidderSeatBid.of( - singletonList(BidderBid.of(Bid.builder().id("bid1").build(), BidType.banner, "EUR"))), + singletonList(BidderBid.of( + Bid.builder().id("bid1").build(), BidType.banner, "rubicon", "EUR"))), 100); final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() .bidder("rubicon") @@ -691,10 +696,12 @@ public void mergeWithBidderResponsesShouldResolveCurrencyFromBidderResponse() { BidderBid.of( Bid.builder().id("bid2").impid("storedImp").build(), BidType.banner, + "rubicon", "EUR"), BidderBid.of( Bid.builder().id("bid1").build(), BidType.banner, + "rubicon", "EUR")); verify(rubiconBidRejectionTracker).restoreFromRejection(expectedBids); @@ -711,7 +718,8 @@ public void mergeWithBidderResponsesShouldResolveBidTypeFromStoredBidExt() { final BidderResponse bidderResponse = BidderResponse.of( "rubicon", BidderSeatBid.of( - singletonList(BidderBid.of(Bid.builder().id("bid1").build(), BidType.banner, "USD"))), + singletonList(BidderBid.of( + Bid.builder().id("bid1").build(), BidType.banner, "rubicon", "USD"))), 100); final AuctionParticipation requestAuctionParticipation = AuctionParticipation.builder() .bidder("rubicon") @@ -748,8 +756,8 @@ public void mergeWithBidderResponsesShouldResolveBidTypeFromStoredBidExt() { .impid("storedImp") .ext(mapper.createObjectNode() .set("prebid", mapper.valueToTree(extBidPrebid))).build(), - BidType.video, "USD"), - BidderBid.of(Bid.builder().id("bid1").build(), BidType.banner, "USD")); + BidType.video, "rubicon", "USD"), + BidderBid.of(Bid.builder().id("bid1").build(), BidType.banner, "rubicon", "USD")); verify(rubiconBidRejectionTracker).restoreFromRejection(expectedBids); verifyNoInteractions(appnexusBidRejectionTracker); From e95f41660db69b666cce1a4d53dbfd7fe20c513f Mon Sep 17 00:00:00 2001 From: antonbabak Date: Wed, 19 Mar 2025 10:59:54 +0100 Subject: [PATCH 19/23] Fix comments --- .../v1/Ortb2BlockingBidderRequestHook.java | 2 +- .../server/auction/BidResponseCreator.java | 21 +++--- .../prebid/server/auction/BidsAdjuster.java | 7 +- .../server/auction/ExchangeService.java | 53 ++++++-------- .../prebid/server/auction/ImpAdjuster.java | 1 + .../org/prebid/server/auction/UidUpdater.java | 1 + .../aliases}/AlternateBidder.java | 2 +- .../aliases/AlternateBidderCodesConfig.java | 10 +++ .../auction/{ => aliases}/BidderAliases.java | 49 +++++-------- .../BidderMediaTypeProcessor.java | 2 +- .../CompositeMediaTypeProcessor.java | 2 +- .../MediaTypeProcessor.java | 2 +- .../MultiFormatMediaTypeProcessor.java | 2 +- .../enforcement/ActivityEnforcement.java | 2 +- .../privacy/enforcement/CcpaEnforcement.java | 2 +- .../privacy/enforcement/CoppaEnforcement.java | 2 +- .../enforcement/PrivacyEnforcement.java | 2 +- .../PrivacyEnforcementService.java | 2 +- .../privacy/enforcement/TcfEnforcement.java | 2 +- .../Ortb2ImplicitParametersResolver.java | 2 +- .../bidder/HttpBidderRequestEnricher.java | 2 +- .../server/bidder/HttpBidderRequester.java | 2 +- .../server/privacy/gdpr/VendorIdResolver.java | 2 +- .../ExtRequestPrebidAlternateBidderCodes.java | 7 +- ...questPrebidAlternateBidderCodesBidder.java | 5 +- .../model/AccountAlternateBidderCodes.java | 7 +- .../AccountAlternateBidderCodesBidder.java | 6 +- .../server/validation/ImpValidator.java | 2 +- .../validation/ResponseBidValidator.java | 2 +- .../auction/BidResponseCreatorTest.java | 1 + .../server/auction/BidderAliasesTest.java | 69 +++++++------------ .../server/auction/ExchangeServiceTest.java | 24 ++----- .../server/auction/ImpAdjusterTest.java | 1 + .../prebid/server/auction/UidUpdaterTest.java | 1 + .../BidderMediaTypeProcessorTest.java | 2 +- .../CompositeMediaTypeProcessorTest.java | 2 +- .../MultiFormatMediaTypeProcessorTest.java | 2 +- .../enforcement/ActivityEnforcementTest.java | 2 +- .../enforcement/CcpaEnforcementTest.java | 2 +- .../enforcement/CoppaEnforcementTest.java | 2 +- .../PrivacyEnforcementServiceTest.java | 2 +- .../enforcement/TcfEnforcementTest.java | 2 +- .../bidder/HttpBidderRequestEnricherTest.java | 2 +- .../bidder/HttpBidderRequesterTest.java | 2 +- .../validation/ResponseBidValidatorTest.java | 2 +- 45 files changed, 136 insertions(+), 185 deletions(-) rename src/main/java/org/prebid/server/{proto/openrtb/ext/request => auction/aliases}/AlternateBidder.java (71%) create mode 100644 src/main/java/org/prebid/server/auction/aliases/AlternateBidderCodesConfig.java rename src/main/java/org/prebid/server/auction/{ => aliases}/BidderAliases.java (68%) diff --git a/extra/modules/ortb2-blocking/src/main/java/org/prebid/server/hooks/modules/ortb2/blocking/v1/Ortb2BlockingBidderRequestHook.java b/extra/modules/ortb2-blocking/src/main/java/org/prebid/server/hooks/modules/ortb2/blocking/v1/Ortb2BlockingBidderRequestHook.java index 6ef69c93140..e13deb60d3d 100644 --- a/extra/modules/ortb2-blocking/src/main/java/org/prebid/server/hooks/modules/ortb2/blocking/v1/Ortb2BlockingBidderRequestHook.java +++ b/extra/modules/ortb2-blocking/src/main/java/org/prebid/server/hooks/modules/ortb2/blocking/v1/Ortb2BlockingBidderRequestHook.java @@ -2,7 +2,7 @@ import com.iab.openrtb.request.BidRequest; import io.vertx.core.Future; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.versionconverter.OrtbVersion; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.hooks.execution.v1.InvocationResultImpl; diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 1623ab53070..33db1e5db26 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -23,6 +23,7 @@ import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.categorymapping.CategoryMappingService; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.AuctionParticipation; @@ -769,24 +770,16 @@ private static List injectTargeting(List bidderImpIdBidInfos, final int multiBidSize = bidderImpIdBidInfos.size(); for (int i = 0; i < multiBidSize; i++) { // first bid have the highest value and can't be extra bid - final boolean isFirstBid = i == 0; - final String targetingBidderCode = isFirstBid - ? bidder - : bidderCodePrefix == null ? null : bidderCodePrefix + (i + 1); - + final String targetingBidderCode = targetingCode(bidder, bidderCodePrefix, i); final BidInfo bidInfo = bidderImpIdBidInfos.get(i); - final String targetingSeat = isFirstBid - ? bidInfo.getSeat() - : bidderCodePrefix == null ? null : bidderCodePrefix + (i + 1); - final TargetingInfo targetingInfo = TargetingInfo.builder() .isTargetingEnabled(targetingBidderCode != null) .isBidderWinningBid(winningBidsByBidder.contains(bidInfo)) .isWinningBid(winningBids.contains(bidInfo)) .isAddTargetBidderCode(targetingBidderCode != null && multiBidSize > 1) .bidderCode(targetingBidderCode) - .seat(targetingSeat) + .seat(targetingCode(bidInfo.getSeat(), bidderCodePrefix, i)) .build(); final BidInfo modifiedBidInfo = bidInfo.toBuilder().targetingInfo(targetingInfo).build(); @@ -796,6 +789,14 @@ private static List injectTargeting(List bidderImpIdBidInfos, return result; } + private static String targetingCode(String base, String prefix, int i) { + if (i == 0) { + return base; + } + + return prefix != null ? prefix + (i + 1) : null; + } + /** * Returns {@link ExtBidResponse} object, populated with response time, errors and debug info (if requested) * from all bidders. diff --git a/src/main/java/org/prebid/server/auction/BidsAdjuster.java b/src/main/java/org/prebid/server/auction/BidsAdjuster.java index 39dd941eb43..f79b6dd7e6c 100644 --- a/src/main/java/org/prebid/server/auction/BidsAdjuster.java +++ b/src/main/java/org/prebid/server/auction/BidsAdjuster.java @@ -2,6 +2,7 @@ import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.response.Bid; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.AuctionParticipation; import org.prebid.server.auction.model.BidderResponse; @@ -43,11 +44,7 @@ public List validateAndAdjustBids(List validBidderResponse( - auctionParticipation, - auctionContext, - aliases)) - + .map(auctionParticipation -> validBidderResponse(auctionParticipation, auctionContext, aliases)) .map(auctionParticipation -> bidAdjustmentsProcessor.enrichWithAdjustedBids( auctionParticipation, auctionContext.getBidRequest(), diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index 0b5df3ed25b..dfdf64a21a5 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -28,6 +28,8 @@ import org.prebid.server.activity.infrastructure.payload.ActivityInvocationPayload; import org.prebid.server.activity.infrastructure.payload.impl.ActivityInvocationPayloadImpl; import org.prebid.server.activity.infrastructure.payload.impl.BidRequestActivityInvocationPayload; +import org.prebid.server.auction.aliases.AlternateBidderCodesConfig; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.mediatypeprocessor.MediaTypeProcessingResult; import org.prebid.server.auction.mediatypeprocessor.MediaTypeProcessor; import org.prebid.server.auction.model.AuctionContext; @@ -271,10 +273,8 @@ private Future runAuction(AuctionContext receivedContext) { context.getBidRejectionTrackers())) .map(auctionParticipations -> dropZeroNonDealBids( auctionParticipations, debugWarnings, debugEnabled)) - .map(auctionParticipations -> bidsAdjuster.validateAndAdjustBids( - auctionParticipations, - context, - aliases)) + .map(auctionParticipations -> + bidsAdjuster.validateAndAdjustBids(auctionParticipations, context, aliases)) .map(auctionParticipations -> updateResponsesMetrics(auctionParticipations, account, aliases)) .map(context::with)) // produce response from bidder results @@ -297,9 +297,11 @@ private BidderAliases aliases(BidRequest bidRequest, Account account) { ? prebid.getAlternateBidderCodes() : null; - return alternateBidderCodes != null - ? BidderAliases.of(aliases, aliasgvlids, bidderCatalog, alternateBidderCodes) - : BidderAliases.of(aliases, aliasgvlids, bidderCatalog, account.getAlternateBidderCodes()); + final AlternateBidderCodesConfig alternateBidderCodesConfig = ObjectUtils.defaultIfNull( + alternateBidderCodes, + account.getAlternateBidderCodes()); + + return BidderAliases.of(aliases, aliasgvlids, bidderCatalog, alternateBidderCodesConfig); } private static ExtRequestTargeting targeting(BidRequest bidRequest) { @@ -1246,42 +1248,31 @@ private BidderSeatBid populateBidderCode(BidderSeatBid seatBid, String bidderNam .seat(ObjectUtils.defaultIfNull(bidderBid.getSeat(), bidderName)) .bid(bidderBid.getBid().toBuilder() .ext(prepareBidExt( - bidderBid.getBid(), + bidderBid.getBid().getExt(), bidderCatalog.configuredName(resolvedBidderName))) .build()) .build()) .toList()); } - private ObjectNode prepareBidExt(Bid bid, String bidderName) { - final ObjectNode bidExt = bid.getExt(); - final ObjectNode extPrebid = bidExt != null ? (ObjectNode) bidExt.get(PREBID_EXT) : null; - final ExtBidPrebidMeta meta = extPrebid != null - ? getExtPrebidMeta(extPrebid.get(PREBID_META_EXT)) - : null; + private ObjectNode prepareBidExt(ObjectNode bidExt, String bidderName) { + final ObjectNode updatedBidExt = bidExt != null ? bidExt : mapper.mapper().createObjectNode(); - final ExtBidPrebidMeta updatedMeta = Optional.ofNullable(meta) - .map(ExtBidPrebidMeta::toBuilder) - .orElseGet(ExtBidPrebidMeta::builder) - .adapterCode(bidderName) - .build(); + final ObjectNode extPrebid = objectNodeFromOrNew(updatedBidExt, PREBID_EXT); + final ObjectNode extPrebidMeta = objectNodeFromOrNew(extPrebid, PREBID_META_EXT); - final ObjectNode updatedBidExt = bidExt != null ? bidExt : mapper.mapper().createObjectNode(); - final ObjectNode updatedBidExtPrebid = extPrebid != null ? extPrebid : mapper.mapper().createObjectNode(); - updatedBidExtPrebid.set(PREBID_META_EXT, mapper.mapper().valueToTree(updatedMeta)); - updatedBidExt.set(PREBID_EXT, mapper.mapper().valueToTree(updatedBidExtPrebid)); + final ObjectNode newData = mapper.mapper().valueToTree( + ExtBidPrebidMeta.builder().adapterCode(bidderName).build()); + extPrebidMeta.setAll(newData); return updatedBidExt; } - private ExtBidPrebidMeta getExtPrebidMeta(JsonNode bidExtPrebidMeta) { - try { - return bidExtPrebidMeta != null - ? mapper.mapper().convertValue(bidExtPrebidMeta, ExtBidPrebidMeta.class) - : null; - } catch (IllegalArgumentException e) { - return null; - } + private ObjectNode objectNodeFromOrNew(ObjectNode parent, String key) { + final JsonNode childNode = parent.get(key); + return childNode == null || !childNode.isObject() + ? parent.putObject(key) + : (ObjectNode) childNode; } private BidRequest adjustTmax(BidRequest bidRequest, diff --git a/src/main/java/org/prebid/server/auction/ImpAdjuster.java b/src/main/java/org/prebid/server/auction/ImpAdjuster.java index 52c4ebd447d..2d8be424fea 100644 --- a/src/main/java/org/prebid/server/auction/ImpAdjuster.java +++ b/src/main/java/org/prebid/server/auction/ImpAdjuster.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.node.IntNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.Imp; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.json.JacksonMapper; import org.prebid.server.json.JsonMerger; import org.prebid.server.validation.ImpValidator; diff --git a/src/main/java/org/prebid/server/auction/UidUpdater.java b/src/main/java/org/prebid/server/auction/UidUpdater.java index 5c2390a6db3..014c0d93898 100644 --- a/src/main/java/org/prebid/server/auction/UidUpdater.java +++ b/src/main/java/org/prebid/server/auction/UidUpdater.java @@ -3,6 +3,7 @@ import com.iab.openrtb.request.User; import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.apache.commons.lang3.StringUtils; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.cookie.UidsCookie; diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/AlternateBidder.java b/src/main/java/org/prebid/server/auction/aliases/AlternateBidder.java similarity index 71% rename from src/main/java/org/prebid/server/proto/openrtb/ext/request/AlternateBidder.java rename to src/main/java/org/prebid/server/auction/aliases/AlternateBidder.java index 2c3a7866ebc..aab0494cd4f 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/AlternateBidder.java +++ b/src/main/java/org/prebid/server/auction/aliases/AlternateBidder.java @@ -1,4 +1,4 @@ -package org.prebid.server.proto.openrtb.ext.request; +package org.prebid.server.auction.aliases; import java.util.Set; diff --git a/src/main/java/org/prebid/server/auction/aliases/AlternateBidderCodesConfig.java b/src/main/java/org/prebid/server/auction/aliases/AlternateBidderCodesConfig.java new file mode 100644 index 00000000000..91b619e71c2 --- /dev/null +++ b/src/main/java/org/prebid/server/auction/aliases/AlternateBidderCodesConfig.java @@ -0,0 +1,10 @@ +package org.prebid.server.auction.aliases; + +import java.util.Map; + +public interface AlternateBidderCodesConfig { + + Boolean getEnabled(); + + Map getBidders(); +} diff --git a/src/main/java/org/prebid/server/auction/BidderAliases.java b/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java similarity index 68% rename from src/main/java/org/prebid/server/auction/BidderAliases.java rename to src/main/java/org/prebid/server/auction/aliases/BidderAliases.java index 7b36a90c049..3b8c18b5ead 100644 --- a/src/main/java/org/prebid/server/auction/BidderAliases.java +++ b/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java @@ -1,13 +1,10 @@ -package org.prebid.server.auction; +package org.prebid.server.auction.aliases; import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.BidderCatalog; -import org.prebid.server.proto.openrtb.ext.request.AlternateBidder; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; -import org.prebid.server.settings.model.AccountAlternateBidderCodes; import java.util.Collection; import java.util.Collections; @@ -16,7 +13,6 @@ import java.util.Optional; import java.util.Set; import java.util.TreeSet; -import java.util.function.Function; import java.util.stream.Collectors; /** @@ -55,27 +51,13 @@ public static BidderAliases of(Map aliasToBidder, public static BidderAliases of(Map aliasToBidder, Map aliasToVendorId, BidderCatalog bidderCatalog, - AccountAlternateBidderCodes alternateBidderCodes) { + AlternateBidderCodesConfig alternateBidderCodes) { - final Map> bidderToAllowedSeats = resolveAlternateBidderCodes( - alternateBidderCodes, - AccountAlternateBidderCodes::getEnabled, - AccountAlternateBidderCodes::getBidders); - - return new BidderAliases(aliasToBidder, aliasToVendorId, bidderToAllowedSeats, bidderCatalog); - } - - public static BidderAliases of(Map aliasToBidder, - Map aliasToVendorId, - BidderCatalog bidderCatalog, - ExtRequestPrebidAlternateBidderCodes alternateBidderCodes) { - - final Map> bidderToAllowedSeats = resolveAlternateBidderCodes( - alternateBidderCodes, - ExtRequestPrebidAlternateBidderCodes::getEnabled, - ExtRequestPrebidAlternateBidderCodes::getBidders); - - return new BidderAliases(aliasToBidder, aliasToVendorId, bidderToAllowedSeats, bidderCatalog); + return new BidderAliases( + aliasToBidder, + aliasToVendorId, + resolveAlternateBidderCodes(alternateBidderCodes), + bidderCatalog); } public boolean isAliasDefined(String alias) { @@ -108,13 +90,11 @@ public boolean isAllowedAlternateBidderCode(String bidder, String alternateBidde } private static Map> resolveAlternateBidderCodes( - T alternateBidderCodes, - Function isEnabled, - Function> getBidders) { + AlternateBidderCodesConfig alternateBidderCodes) { return Optional.ofNullable(alternateBidderCodes) - .filter(codes -> BooleanUtils.isTrue(isEnabled.apply(codes))) - .map(getBidders::apply) + .filter(config -> BooleanUtils.isTrue(config.getEnabled())) + .map(AlternateBidderCodesConfig::getBidders) .map(Map::entrySet) .stream() .flatMap(Collection::stream) @@ -129,8 +109,13 @@ private static Map> resolveAlternateBidderCodes( private static Set allowedBidderCodes(AlternateBidder alternateBidder) { final Set allowedBidderCodes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - Optional.ofNullable(alternateBidder.getAllowedBidderCodes()) - .ifPresentOrElse(allowedBidderCodes::addAll, () -> allowedBidderCodes.add(WILDCARD)); + final Set alternateCodes = alternateBidder.getAllowedBidderCodes(); + + if (alternateCodes == null) { + allowedBidderCodes.add(WILDCARD); + } else { + allowedBidderCodes.addAll(alternateCodes); + } return allowedBidderCodes; } } diff --git a/src/main/java/org/prebid/server/auction/mediatypeprocessor/BidderMediaTypeProcessor.java b/src/main/java/org/prebid/server/auction/mediatypeprocessor/BidderMediaTypeProcessor.java index 0171ff90b68..17828059175 100644 --- a/src/main/java/org/prebid/server/auction/mediatypeprocessor/BidderMediaTypeProcessor.java +++ b/src/main/java/org/prebid/server/auction/mediatypeprocessor/BidderMediaTypeProcessor.java @@ -3,7 +3,7 @@ import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Imp; import org.apache.commons.collections4.SetUtils; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.bidder.BidderInfo; import org.prebid.server.bidder.model.BidderError; diff --git a/src/main/java/org/prebid/server/auction/mediatypeprocessor/CompositeMediaTypeProcessor.java b/src/main/java/org/prebid/server/auction/mediatypeprocessor/CompositeMediaTypeProcessor.java index c51d35eb33f..5dbd2bb3ae6 100644 --- a/src/main/java/org/prebid/server/auction/mediatypeprocessor/CompositeMediaTypeProcessor.java +++ b/src/main/java/org/prebid/server/auction/mediatypeprocessor/CompositeMediaTypeProcessor.java @@ -1,7 +1,7 @@ package org.prebid.server.auction.mediatypeprocessor; import com.iab.openrtb.request.BidRequest; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.bidder.model.BidderError; import org.prebid.server.settings.model.Account; diff --git a/src/main/java/org/prebid/server/auction/mediatypeprocessor/MediaTypeProcessor.java b/src/main/java/org/prebid/server/auction/mediatypeprocessor/MediaTypeProcessor.java index 89e7f07589b..0cf5f19bd6a 100644 --- a/src/main/java/org/prebid/server/auction/mediatypeprocessor/MediaTypeProcessor.java +++ b/src/main/java/org/prebid/server/auction/mediatypeprocessor/MediaTypeProcessor.java @@ -1,7 +1,7 @@ package org.prebid.server.auction.mediatypeprocessor; import com.iab.openrtb.request.BidRequest; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.settings.model.Account; public interface MediaTypeProcessor { diff --git a/src/main/java/org/prebid/server/auction/mediatypeprocessor/MultiFormatMediaTypeProcessor.java b/src/main/java/org/prebid/server/auction/mediatypeprocessor/MultiFormatMediaTypeProcessor.java index af0a9e2428c..0fda09f919e 100644 --- a/src/main/java/org/prebid/server/auction/mediatypeprocessor/MultiFormatMediaTypeProcessor.java +++ b/src/main/java/org/prebid/server/auction/mediatypeprocessor/MultiFormatMediaTypeProcessor.java @@ -4,7 +4,7 @@ import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Imp; import org.apache.commons.lang3.StringUtils; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.bidder.model.BidderError; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; diff --git a/src/main/java/org/prebid/server/auction/privacy/enforcement/ActivityEnforcement.java b/src/main/java/org/prebid/server/auction/privacy/enforcement/ActivityEnforcement.java index 395dff73802..009b14ade2a 100644 --- a/src/main/java/org/prebid/server/auction/privacy/enforcement/ActivityEnforcement.java +++ b/src/main/java/org/prebid/server/auction/privacy/enforcement/ActivityEnforcement.java @@ -12,7 +12,7 @@ import org.prebid.server.activity.infrastructure.payload.ActivityInvocationPayload; import org.prebid.server.activity.infrastructure.payload.impl.ActivityInvocationPayloadImpl; import org.prebid.server.activity.infrastructure.payload.impl.PrivacyEnforcementServiceActivityInvocationPayload; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask; diff --git a/src/main/java/org/prebid/server/auction/privacy/enforcement/CcpaEnforcement.java b/src/main/java/org/prebid/server/auction/privacy/enforcement/CcpaEnforcement.java index 51a8d8f4622..dd9c9b0e580 100644 --- a/src/main/java/org/prebid/server/auction/privacy/enforcement/CcpaEnforcement.java +++ b/src/main/java/org/prebid/server/auction/privacy/enforcement/CcpaEnforcement.java @@ -2,7 +2,7 @@ import com.iab.openrtb.request.BidRequest; import io.vertx.core.Future; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdCcpaMask; diff --git a/src/main/java/org/prebid/server/auction/privacy/enforcement/CoppaEnforcement.java b/src/main/java/org/prebid/server/auction/privacy/enforcement/CoppaEnforcement.java index 9ebe0c8d044..8b273b665df 100644 --- a/src/main/java/org/prebid/server/auction/privacy/enforcement/CoppaEnforcement.java +++ b/src/main/java/org/prebid/server/auction/privacy/enforcement/CoppaEnforcement.java @@ -1,7 +1,7 @@ package org.prebid.server.auction.privacy.enforcement; import io.vertx.core.Future; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdCoppaMask; diff --git a/src/main/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcement.java b/src/main/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcement.java index d12e290fb2e..6ff56836e79 100644 --- a/src/main/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcement.java +++ b/src/main/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcement.java @@ -1,7 +1,7 @@ package org.prebid.server.auction.privacy.enforcement; import io.vertx.core.Future; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; diff --git a/src/main/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcementService.java b/src/main/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcementService.java index f50a7c637f6..9d18300197b 100644 --- a/src/main/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcementService.java +++ b/src/main/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcementService.java @@ -2,7 +2,7 @@ import com.iab.openrtb.request.User; import io.vertx.core.Future; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; diff --git a/src/main/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcement.java b/src/main/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcement.java index e8409ecb359..4bac7952375 100644 --- a/src/main/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcement.java +++ b/src/main/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcement.java @@ -6,7 +6,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdTcfMask; diff --git a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java index 5bcabe413db..5446da183ad 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java @@ -24,7 +24,7 @@ import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.ImplicitParametersExtractor; import org.prebid.server.auction.IpAddressHelper; import org.prebid.server.auction.PriceGranularity; diff --git a/src/main/java/org/prebid/server/bidder/HttpBidderRequestEnricher.java b/src/main/java/org/prebid/server/bidder/HttpBidderRequestEnricher.java index 4aabd5960a5..4872c6fd991 100644 --- a/src/main/java/org/prebid/server/bidder/HttpBidderRequestEnricher.java +++ b/src/main/java/org/prebid/server/bidder/HttpBidderRequestEnricher.java @@ -5,7 +5,7 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.vertx.core.MultiMap; import org.apache.commons.lang3.StringUtils; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.model.CaseInsensitiveMultiMap; import org.prebid.server.proto.openrtb.ext.request.ExtApp; import org.prebid.server.proto.openrtb.ext.request.ExtAppPrebid; diff --git a/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java b/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java index 3a24683c774..d3b9d452eac 100644 --- a/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java +++ b/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java @@ -9,7 +9,7 @@ import io.vertx.core.MultiMap; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.ExchangeService; import org.prebid.server.auction.model.BidRejectionReason; import org.prebid.server.auction.model.BidRejectionTracker; diff --git a/src/main/java/org/prebid/server/privacy/gdpr/VendorIdResolver.java b/src/main/java/org/prebid/server/privacy/gdpr/VendorIdResolver.java index 5c646d3b925..d8d360fa823 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/VendorIdResolver.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/VendorIdResolver.java @@ -1,6 +1,6 @@ package org.prebid.server.privacy.gdpr; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.bidder.BidderCatalog; public class VendorIdResolver { diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodes.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodes.java index 578d5402f8b..60dc15956db 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodes.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodes.java @@ -1,13 +1,12 @@ package org.prebid.server.proto.openrtb.ext.request; -import lombok.Builder; import lombok.Value; +import org.prebid.server.auction.aliases.AlternateBidderCodesConfig; import java.util.Map; -@Builder(toBuilder = true) -@Value -public class ExtRequestPrebidAlternateBidderCodes { +@Value(staticConstructor = "of") +public class ExtRequestPrebidAlternateBidderCodes implements AlternateBidderCodesConfig { Boolean enabled; diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java index 1500a01c6c8..61caa45e792 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidAlternateBidderCodesBidder.java @@ -1,13 +1,12 @@ package org.prebid.server.proto.openrtb.ext.request; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; import lombok.Value; +import org.prebid.server.auction.aliases.AlternateBidder; import java.util.Set; -@Builder(toBuilder = true) -@Value +@Value(staticConstructor = "of") public class ExtRequestPrebidAlternateBidderCodesBidder implements AlternateBidder { Boolean enabled; diff --git a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java index ffbebc0d5c6..bcf8e937eb8 100644 --- a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java +++ b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodes.java @@ -1,13 +1,12 @@ package org.prebid.server.settings.model; -import lombok.Builder; import lombok.Value; +import org.prebid.server.auction.aliases.AlternateBidderCodesConfig; import java.util.Map; -@Builder(toBuilder = true) -@Value -public class AccountAlternateBidderCodes { +@Value(staticConstructor = "of") +public class AccountAlternateBidderCodes implements AlternateBidderCodesConfig { Boolean enabled; diff --git a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java index 0ed42dbe70d..50f230133d5 100644 --- a/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java +++ b/src/main/java/org/prebid/server/settings/model/AccountAlternateBidderCodesBidder.java @@ -1,14 +1,12 @@ package org.prebid.server.settings.model; import com.fasterxml.jackson.annotation.JsonAlias; -import lombok.Builder; import lombok.Value; -import org.prebid.server.proto.openrtb.ext.request.AlternateBidder; +import org.prebid.server.auction.aliases.AlternateBidder; import java.util.Set; -@Builder(toBuilder = true) -@Value +@Value(staticConstructor = "of") public class AccountAlternateBidderCodesBidder implements AlternateBidder { Boolean enabled; diff --git a/src/main/java/org/prebid/server/validation/ImpValidator.java b/src/main/java/org/prebid/server/validation/ImpValidator.java index b2a2e3b0bed..9a31aa6e52d 100644 --- a/src/main/java/org/prebid/server/validation/ImpValidator.java +++ b/src/main/java/org/prebid/server/validation/ImpValidator.java @@ -28,7 +28,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.json.JacksonMapper; import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; diff --git a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java index 242114516e3..252f0bf8368 100644 --- a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java +++ b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java @@ -9,7 +9,7 @@ import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidRejectionReason; import org.prebid.server.auction.model.BidRejectionTracker; diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index 482a85b8c46..ba7fab62c86 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -33,6 +33,7 @@ import org.prebid.server.activity.Activity; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; import org.prebid.server.activity.infrastructure.rule.Rule; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.categorymapping.CategoryMappingService; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.AuctionParticipation; diff --git a/src/test/java/org/prebid/server/auction/BidderAliasesTest.java b/src/test/java/org/prebid/server/auction/BidderAliasesTest.java index ac0a2137cb6..b6adf02682e 100644 --- a/src/test/java/org/prebid/server/auction/BidderAliasesTest.java +++ b/src/test/java/org/prebid/server/auction/BidderAliasesTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodesBidder; @@ -198,13 +199,9 @@ public void resolveAliasVendorIdShouldReturnVendorIdFromBidderCatalogWhenVendorI @Test public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreDisabledForBidder() { // given - final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(false) - .allowedBidderCodes(Set.of("seat")) - .build())) - .build(); + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.of(false, Set.of("seat")))); final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); // when and then @@ -214,13 +211,9 @@ public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCode @Test public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreLackingSeat() { // given - final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("anotherSeat")) - .build())) - .build(); + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("another")))); final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); // when and then @@ -230,10 +223,9 @@ public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCode @Test public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreLackingBidders() { // given - final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(null) - .build(); + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + null); final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); // when and then @@ -243,13 +235,9 @@ public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCode @Test public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreDisabled() { // given - final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(false) - .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("seat")) - .build())) - .build(); + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + false, + Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("seat")))); final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); // when and then @@ -259,13 +247,9 @@ public void isAllowedAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCode @Test public void isAllowedAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCodesAreNull() { // given - final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(null) - .build())) - .build(); + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.of(true, null))); final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); // when and then @@ -275,13 +259,9 @@ public void isAllowedAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCode @Test public void isAllowedAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCodesContainsWildcard() { // given - final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("*")) - .build())) - .build(); + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("*")))); final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); // when and then @@ -291,13 +271,10 @@ public void isAllowedAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCode @Test public void isAllowedAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCodesContainsSeatCaseInsensitive() { // given - final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of("BiDDEr", ExtRequestPrebidAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("SeaT")) - .build())) - .build(); + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("BiDDEr", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("SeaT")))); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); // when and then diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index c1007ad9329..d1d68c785a5 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -3075,7 +3075,7 @@ public void shouldValidateBidsWithExtRequestPrebidAlternateBidderCodes() { givenBidderBid(Bid.builder().impid("impId").price(TEN).build())))); final ExtRequestPrebidAlternateBidderCodes requestAlternateBidderCodes = - ExtRequestPrebidAlternateBidderCodes.builder().enabled(false).build(); + ExtRequestPrebidAlternateBidderCodes.of(false, null); final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1)), builder -> builder @@ -3083,14 +3083,9 @@ public void shouldValidateBidsWithExtRequestPrebidAlternateBidderCodes() { .alternateBidderCodes(requestAlternateBidderCodes) .build()))); - final AccountAlternateBidderCodes accountAlternateBidderCodes = - AccountAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of("someBidder", AccountAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("seat")) - .build())) - .build(); + final AccountAlternateBidderCodes accountAlternateBidderCodes = AccountAlternateBidderCodes.of( + true, + Map.of("someBidder", AccountAlternateBidderCodesBidder.of(true, Set.of("seat")))); final Account givenAccount = Account.builder() .id("accountId") @@ -3118,14 +3113,9 @@ public void shouldValidateBidsWithAccountAlternateBidderCodesWhenRequestOnesAreA final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1)), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder().build()))); - final AccountAlternateBidderCodes accountAlternateBidderCodes = - AccountAlternateBidderCodes.builder() - .enabled(true) - .bidders(Map.of("someBidder", AccountAlternateBidderCodesBidder.builder() - .enabled(true) - .allowedBidderCodes(Set.of("seat")) - .build())) - .build(); + final AccountAlternateBidderCodes accountAlternateBidderCodes = AccountAlternateBidderCodes.of( + true, + Map.of("someBidder", AccountAlternateBidderCodesBidder.of(true, Set.of("seat")))); final Account givenAccount = Account.builder() .id("accountId") diff --git a/src/test/java/org/prebid/server/auction/ImpAdjusterTest.java b/src/test/java/org/prebid/server/auction/ImpAdjusterTest.java index 06be50d94a6..9dc196f7884 100644 --- a/src/test/java/org/prebid/server/auction/ImpAdjusterTest.java +++ b/src/test/java/org/prebid/server/auction/ImpAdjusterTest.java @@ -12,6 +12,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.VertxTest; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.json.JsonMerger; import org.prebid.server.validation.ImpValidator; diff --git a/src/test/java/org/prebid/server/auction/UidUpdaterTest.java b/src/test/java/org/prebid/server/auction/UidUpdaterTest.java index a076d4c7a43..e6c0af37067 100644 --- a/src/test/java/org/prebid/server/auction/UidUpdaterTest.java +++ b/src/test/java/org/prebid/server/auction/UidUpdaterTest.java @@ -10,6 +10,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.VertxTest; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.cookie.UidsCookie; diff --git a/src/test/java/org/prebid/server/auction/mediatypeprocessor/BidderMediaTypeProcessorTest.java b/src/test/java/org/prebid/server/auction/mediatypeprocessor/BidderMediaTypeProcessorTest.java index 16875667fae..d6e002489f8 100644 --- a/src/test/java/org/prebid/server/auction/mediatypeprocessor/BidderMediaTypeProcessorTest.java +++ b/src/test/java/org/prebid/server/auction/mediatypeprocessor/BidderMediaTypeProcessorTest.java @@ -14,7 +14,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.VertxTest; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.versionconverter.OrtbVersion; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.bidder.BidderInfo; diff --git a/src/test/java/org/prebid/server/auction/mediatypeprocessor/CompositeMediaTypeProcessorTest.java b/src/test/java/org/prebid/server/auction/mediatypeprocessor/CompositeMediaTypeProcessorTest.java index 0ed72d11aa1..0bc3c835600 100644 --- a/src/test/java/org/prebid/server/auction/mediatypeprocessor/CompositeMediaTypeProcessorTest.java +++ b/src/test/java/org/prebid/server/auction/mediatypeprocessor/CompositeMediaTypeProcessorTest.java @@ -6,7 +6,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.bidder.model.BidderError; import static java.util.Arrays.asList; diff --git a/src/test/java/org/prebid/server/auction/mediatypeprocessor/MultiFormatMediaTypeProcessorTest.java b/src/test/java/org/prebid/server/auction/mediatypeprocessor/MultiFormatMediaTypeProcessorTest.java index 61bf49b8745..a8da73fe320 100644 --- a/src/test/java/org/prebid/server/auction/mediatypeprocessor/MultiFormatMediaTypeProcessorTest.java +++ b/src/test/java/org/prebid/server/auction/mediatypeprocessor/MultiFormatMediaTypeProcessorTest.java @@ -14,7 +14,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.VertxTest; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.versionconverter.OrtbVersion; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.bidder.BidderInfo; diff --git a/src/test/java/org/prebid/server/auction/privacy/enforcement/ActivityEnforcementTest.java b/src/test/java/org/prebid/server/auction/privacy/enforcement/ActivityEnforcementTest.java index 6e4662a501d..0ffa9111b0c 100644 --- a/src/test/java/org/prebid/server/auction/privacy/enforcement/ActivityEnforcementTest.java +++ b/src/test/java/org/prebid/server/auction/privacy/enforcement/ActivityEnforcementTest.java @@ -9,7 +9,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask; diff --git a/src/test/java/org/prebid/server/auction/privacy/enforcement/CcpaEnforcementTest.java b/src/test/java/org/prebid/server/auction/privacy/enforcement/CcpaEnforcementTest.java index 178e48ff97d..0133741f248 100644 --- a/src/test/java/org/prebid/server/auction/privacy/enforcement/CcpaEnforcementTest.java +++ b/src/test/java/org/prebid/server/auction/privacy/enforcement/CcpaEnforcementTest.java @@ -9,7 +9,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdCcpaMask; diff --git a/src/test/java/org/prebid/server/auction/privacy/enforcement/CoppaEnforcementTest.java b/src/test/java/org/prebid/server/auction/privacy/enforcement/CoppaEnforcementTest.java index 9e9d47d0488..c5e94d3ce56 100644 --- a/src/test/java/org/prebid/server/auction/privacy/enforcement/CoppaEnforcementTest.java +++ b/src/test/java/org/prebid/server/auction/privacy/enforcement/CoppaEnforcementTest.java @@ -9,7 +9,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdCoppaMask; diff --git a/src/test/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcementServiceTest.java b/src/test/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcementServiceTest.java index 4333eebb5d8..906952bc9b3 100644 --- a/src/test/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcementServiceTest.java +++ b/src/test/java/org/prebid/server/auction/privacy/enforcement/PrivacyEnforcementServiceTest.java @@ -8,7 +8,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; diff --git a/src/test/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcementTest.java b/src/test/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcementTest.java index dcecd091334..2c065c386a7 100644 --- a/src/test/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcementTest.java +++ b/src/test/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcementTest.java @@ -12,7 +12,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdTcfMask; diff --git a/src/test/java/org/prebid/server/bidder/HttpBidderRequestEnricherTest.java b/src/test/java/org/prebid/server/bidder/HttpBidderRequestEnricherTest.java index 4773319266a..a6004aa2ece 100644 --- a/src/test/java/org/prebid/server/bidder/HttpBidderRequestEnricherTest.java +++ b/src/test/java/org/prebid/server/bidder/HttpBidderRequestEnricherTest.java @@ -8,7 +8,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.model.CaseInsensitiveMultiMap; import org.prebid.server.proto.openrtb.ext.request.ExtApp; import org.prebid.server.proto.openrtb.ext.request.ExtAppPrebid; diff --git a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java index 2b067ab06d8..f12bb887ca9 100644 --- a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java +++ b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java @@ -21,7 +21,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.VertxTest; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.BidRejectionReason; import org.prebid.server.auction.model.BidRejectionTracker; import org.prebid.server.auction.model.BidderRequest; diff --git a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java index af8590e38de..91969151268 100644 --- a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java @@ -12,7 +12,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.VertxTest; -import org.prebid.server.auction.BidderAliases; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidRejectionReason; import org.prebid.server.auction.model.BidRejectionTracker; From 482bac05f4e7aa79c1ec729430b445c5fc88bb81 Mon Sep 17 00:00:00 2001 From: Markiyan Mykush <95693607+marki1an@users.noreply.github.com> Date: Wed, 19 Mar 2025 12:26:26 +0200 Subject: [PATCH 20/23] Test: `Multiple biddercode support` (#3687) --- .../functional/model/bidder/BidderName.groovy | 6 +- .../model/bidder/GeneralBidderAdapter.groovy | 6 + .../model/config/AccountConfig.groovy | 3 + .../model/config/AlternateBidderCodes.groovy | 16 + .../model/config/BidderConfig.groovy | 21 + .../model/request/auction/Amx.groovy | 17 + .../model/request/auction/Bidder.groovy | 5 + .../model/request/auction/Prebid.groovy | 4 + .../model/response/auction/BidExt.groovy | 10 + .../model/response/auction/ErrorType.groovy | 4 +- .../model/response/auction/Meta.groovy | 5 +- .../server/functional/tests/AliasSpec.groovy | 6 +- .../tests/AlternateBidderCodeSpec.groovy | 1436 +++++++++++++++++ .../functional/tests/BidAdjustmentSpec.groovy | 74 +- .../functional/tests/BidderParamsSpec.groovy | 370 ++++- .../ResponseCorrectionSpec.groovy | 4 +- 16 files changed, 1969 insertions(+), 18 deletions(-) create mode 100644 src/test/groovy/org/prebid/server/functional/model/config/AlternateBidderCodes.groovy create mode 100644 src/test/groovy/org/prebid/server/functional/model/config/BidderConfig.groovy create mode 100644 src/test/groovy/org/prebid/server/functional/model/request/auction/Amx.groovy create mode 100644 src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy diff --git a/src/test/groovy/org/prebid/server/functional/model/bidder/BidderName.groovy b/src/test/groovy/org/prebid/server/functional/model/bidder/BidderName.groovy index 54e0a451fc6..702918fa886 100644 --- a/src/test/groovy/org/prebid/server/functional/model/bidder/BidderName.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/bidder/BidderName.groovy @@ -11,6 +11,7 @@ enum BidderName { BOGUS("bogus"), ALIAS("alias"), ALIAS_CAMEL_CASE("AlIaS"), + ALIAS_UPPER_CASE("ALIAS"), GENERIC_CAMEL_CASE("GeNerIc"), GENERIC("generic"), GENER_X("gener_x"), @@ -25,7 +26,10 @@ enum BidderName { ADKERNEL("adkernel"), IX("ix"), GRID("grid"), - MEDIANET("medianet") + MEDIANET("medianet"), + AMX("amx"), + AMX_CAMEL_CASE("AmX"), + AMX_UPPER_CASE("AMX"), @JsonValue final String value diff --git a/src/test/groovy/org/prebid/server/functional/model/bidder/GeneralBidderAdapter.groovy b/src/test/groovy/org/prebid/server/functional/model/bidder/GeneralBidderAdapter.groovy index 3184fb17fee..b583363974c 100644 --- a/src/test/groovy/org/prebid/server/functional/model/bidder/GeneralBidderAdapter.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/bidder/GeneralBidderAdapter.groovy @@ -1,8 +1,14 @@ package org.prebid.server.functional.model.bidder +import com.fasterxml.jackson.annotation.JsonProperty + class GeneralBidderAdapter extends Generic { String siteId List size String sid + @JsonProperty("ds") + String demandSource + @JsonProperty("bc") + BidderName bidderCode } diff --git a/src/test/groovy/org/prebid/server/functional/model/config/AccountConfig.groovy b/src/test/groovy/org/prebid/server/functional/model/config/AccountConfig.groovy index 60563ac2f5e..9dded674fee 100644 --- a/src/test/groovy/org/prebid/server/functional/model/config/AccountConfig.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/config/AccountConfig.groovy @@ -23,6 +23,9 @@ class AccountConfig { AccountSetting settings @JsonProperty("cookie_sync") AccountCookieSyncConfig cookieSyncSnakeCase + AlternateBidderCodes alternateBidderCodes + @JsonProperty("alternate_bidder_codes") + AlternateBidderCodes alternateBidderCodesSnakeCase static getDefaultAccountConfig() { new AccountConfig(status: AccountStatus.ACTIVE) diff --git a/src/test/groovy/org/prebid/server/functional/model/config/AlternateBidderCodes.groovy b/src/test/groovy/org/prebid/server/functional/model/config/AlternateBidderCodes.groovy new file mode 100644 index 00000000000..465acaad2cc --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/config/AlternateBidderCodes.groovy @@ -0,0 +1,16 @@ +package org.prebid.server.functional.model.config + +import com.fasterxml.jackson.databind.PropertyNamingStrategies +import com.fasterxml.jackson.databind.annotation.JsonNaming +import groovy.transform.EqualsAndHashCode +import groovy.transform.ToString +import org.prebid.server.functional.model.bidder.BidderName + +@EqualsAndHashCode +@ToString(includeNames = true, ignoreNulls = true) +@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy) +class AlternateBidderCodes { + + Boolean enabled + Map bidders +} diff --git a/src/test/groovy/org/prebid/server/functional/model/config/BidderConfig.groovy b/src/test/groovy/org/prebid/server/functional/model/config/BidderConfig.groovy new file mode 100644 index 00000000000..e139419e4e3 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/config/BidderConfig.groovy @@ -0,0 +1,21 @@ +package org.prebid.server.functional.model.config + +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.databind.PropertyNamingStrategies +import com.fasterxml.jackson.databind.annotation.JsonNaming +import groovy.transform.EqualsAndHashCode +import groovy.transform.ToString +import org.prebid.server.functional.model.bidder.BidderName + +@EqualsAndHashCode +@ToString(includeNames = true, ignoreNulls = true) +@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy) +class BidderConfig { + + Boolean enabled + List allowedBidderCodes + @JsonProperty("allowedbiddercodes") + List allowedBidderCodesLowerCase + @JsonProperty("allowed_bidder_codes") + List allowedBidderCodesSnakeCase +} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Amx.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Amx.groovy new file mode 100644 index 00000000000..3ae0dcd17a3 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Amx.groovy @@ -0,0 +1,17 @@ +package org.prebid.server.functional.model.request.auction + +import com.fasterxml.jackson.annotation.JsonProperty +import org.prebid.server.functional.model.bidder.BidderAdapter +import org.prebid.server.functional.model.bidder.BidderName + +class Amx implements BidderAdapter { + + @JsonProperty("ct") + Integer creativeType + @JsonProperty("startdelay") + Integer startDelay + @JsonProperty("ds") + String demandSource + @JsonProperty("bc") + BidderName bidderCode +} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Bidder.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Bidder.groovy index 125faa37c4b..9c4a17ec5cf 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Bidder.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Bidder.groovy @@ -12,6 +12,8 @@ import org.prebid.server.functional.model.bidder.Rubicon class Bidder { Generic alias + @JsonProperty("ALIAS") + Generic aliasUpperCase Generic generic @JsonProperty("gener_x") Generic generX @@ -26,6 +28,9 @@ class Bidder { Openx openxAlias Adrino adrino Generic nativo + Amx amx + @JsonProperty("AMX") + Amx amxUpperCase static Bidder getDefaultBidder() { new Bidder().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 30149d1a5ee..499dccea5a3 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 @@ -1,10 +1,12 @@ package org.prebid.server.functional.model.request.auction +import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming import groovy.transform.ToString import org.prebid.server.functional.model.ChannelType import org.prebid.server.functional.model.bidder.BidderName +import org.prebid.server.functional.model.config.AlternateBidderCodes @JsonNaming(PropertyNamingStrategies.LowerCaseStrategy) @ToString(includeNames = true, ignoreNulls = true) @@ -41,6 +43,8 @@ class Prebid { PrebidAnalytics analytics StoredAuctionResponse storedAuctionResponse PaaFormat paaFormat + @JsonProperty("alternatebiddercodes") + AlternateBidderCodes alternateBidderCodes static class Channel { diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/BidExt.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/BidExt.groovy index 61cdd7ad5f0..58d2e2178e3 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/BidExt.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/BidExt.groovy @@ -1,7 +1,9 @@ package org.prebid.server.functional.model.response.auction +import com.fasterxml.jackson.annotation.JsonProperty import groovy.transform.ToString import org.prebid.server.functional.model.Currency +import org.prebid.server.functional.model.bidder.BidderName @ToString(includeNames = true, ignoreNulls = true) class BidExt { @@ -10,4 +12,12 @@ class BidExt { BigDecimal origbidcpm Currency origbidcur DsaResponse dsa + @JsonProperty("ct") + Integer creativeType + @JsonProperty("startdelay") + Integer startDelay + @JsonProperty("ds") + String demandSource + @JsonProperty("bc") + BidderName bidderCode } diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/ErrorType.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/ErrorType.groovy index 267a23cc067..80f504a05ec 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/ErrorType.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/ErrorType.groovy @@ -14,7 +14,9 @@ enum ErrorType { ALIAS("alias"), TARGETING("targeting"), IX("ix"), - OPENX("openx") + OPENX("openx"), + AMX("amx"), + AMX_UPPER_CASE("AMX"), @JsonValue final String value diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/Meta.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/Meta.groovy index d022daf9646..e8bb869ebae 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/Meta.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/Meta.groovy @@ -1,12 +1,15 @@ package org.prebid.server.functional.model.response.auction +import com.fasterxml.jackson.annotation.JsonProperty import groovy.transform.ToString +import org.prebid.server.functional.model.bidder.BidderName import org.prebid.server.functional.model.request.auction.RendererData @ToString(includeNames = true, ignoreNulls = true) class Meta { - String adapterCode + @JsonProperty("adaptercode") + BidderName adapterCode List advertiserDomains Integer advertiserId String advertiserName diff --git a/src/test/groovy/org/prebid/server/functional/tests/AliasSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AliasSpec.groovy index 4e544498f44..9013978f76f 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AliasSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AliasSpec.groovy @@ -110,7 +110,7 @@ class AliasSpec extends BaseSpec { then: "Request should fail with error" def exception = thrown(PrebidServerException) assert exception.responseBody.contains("Invalid request format: request.ext.prebid.aliasgvlids. " + - "vendorId ${validId} refers to unknown bidder alias: ${bidderName}") + "vendorId ${validId} refers to unknown bidder alias: ${bidderName.toLowerCase()}") } def "PBS should return an error when GVL ID alias value is lower that one"() { @@ -126,7 +126,7 @@ class AliasSpec extends BaseSpec { then: "Request should fail with error" def exception = thrown(PrebidServerException) assert exception.responseBody.contains("Invalid request format: request.ext.prebid.aliasgvlids. " + - "Invalid vendorId ${invalidId} for alias: ${bidderName}. Choose a different vendorId, or remove this entry.") + "Invalid vendorId ${invalidId} for alias: ${bidderName.toLowerCase()}. Choose a different vendorId, or remove this entry.") where: invalidId << [PBSUtils.randomNegativeNumber, 0] @@ -145,7 +145,7 @@ class AliasSpec extends BaseSpec { then: "Request should fail with an error" def exception = thrown(PrebidServerException) assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: request.ext.prebid.aliases.$randomString " + + assert exception.responseBody == "Invalid request format: request.ext.prebid.aliases.${randomString.toLowerCase()} " + "refers to unknown bidder: $BOGUS.value" } diff --git a/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy new file mode 100644 index 00000000000..048a4983050 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy @@ -0,0 +1,1436 @@ +package org.prebid.server.functional.tests + +import org.prebid.server.functional.model.bidder.Generic +import org.prebid.server.functional.model.config.AccountConfig +import org.prebid.server.functional.model.config.AlternateBidderCodes +import org.prebid.server.functional.model.config.BidderConfig +import org.prebid.server.functional.model.db.Account +import org.prebid.server.functional.model.request.auction.Amx +import org.prebid.server.functional.model.request.auction.BidRequest +import org.prebid.server.functional.model.request.auction.Targeting +import org.prebid.server.functional.model.response.auction.BidExt +import org.prebid.server.functional.model.response.auction.BidResponse +import org.prebid.server.functional.model.response.auction.ErrorType +import org.prebid.server.functional.service.PrebidServerService +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.bidder.BidderName.ALIAS +import static org.prebid.server.functional.model.bidder.BidderName.ALIAS_CAMEL_CASE +import static org.prebid.server.functional.model.bidder.BidderName.AMX +import static org.prebid.server.functional.model.bidder.BidderName.AMX_CAMEL_CASE +import static org.prebid.server.functional.model.bidder.BidderName.BOGUS +import static org.prebid.server.functional.model.bidder.BidderName.EMPTY +import static org.prebid.server.functional.model.bidder.BidderName.GENERIC +import static org.prebid.server.functional.model.bidder.BidderName.GENERIC_CAMEL_CASE +import static org.prebid.server.functional.model.bidder.BidderName.UNKNOWN +import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD +import static org.prebid.server.functional.model.response.auction.BidRejectionReason.RESPONSE_REJECTED_GENERAL +import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer + +class AlternateBidderCodeSpec extends BaseSpec { + + private static final String ADAPTER_RESPONSE_VALIDATION_METRICS = "adapter.%s.response.validation.seat" + private static final String ERROR_BID_CODE_VALIDATION = "BidId `%s` validation messages: " + + "Error: invalid bidder code %s was set by the adapter %s for the account %s" + private static final String INVALID_BIDDER_CODE_LOGS = "invalid bidder code %s was set by the adapter %s for the account %s" + private static final Map AMX_CONFIG = ["adapters.amx.enabled" : "true", + "adapters.amx.endpoint": "$networkServiceContainer.rootUri/auction".toString()] + @Shared + private static final PrebidServerService pbsServiceWithAmxBidder = pbsServiceFactory.getService(AMX_CONFIG) + + @Override + def cleanupSpec() { + pbsServiceFactory.removeContainer(AMX_CONFIG) + } + + def "PBS shouldn't discard bid amx alias when soft alias request with allowed bidder code"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidder().tap { + imp[0].ext.prebid.bidder.alias = new Generic() + imp[0].ext.prebid.bidder.amx = null + ext.prebid.aliases = [(ALIAS.value): AMX] + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: ALIAS) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response should contain seat" + assert response.seatbid.seat == [ALIAS] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${ALIAS}"] + assert targeting["hb_size_${ALIAS}"] + assert targeting["hb_bidder"] == ALIAS.value + assert targeting["hb_bidder_${ALIAS}"] == ALIAS.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and error and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "PBS shouldn't emit validation metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(ALIAS)] + } + + def "PBS should populate meta demand source when bid response with demand source"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Bid response with demand source" + def demandSource = PBSUtils.getRandomString() + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(demandSource: demandSource) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response should contain seat" + assert response.seatbid.seat == [AMX] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain demand source" + assert response.seatbid.bid.ext.prebid.meta.demandSource.flatten() == [demandSource] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${AMX}"] + assert targeting["hb_size_${AMX}"] + assert targeting["hb_bidder"] == AMX.value + assert targeting["hb_bidder_${AMX}"] == AMX.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and error and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "PBS shouldn't emit validation metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + } + + def "PBS shouldn't populate meta demand source when bid response without demand source"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Bid response without demand source" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(demandSource: null) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response should contain seat" + assert response.seatbid.seat == [AMX] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${AMX}"] + assert targeting["hb_size_${AMX}"] + assert targeting["hb_bidder"] == AMX.value + assert targeting["hb_bidder_${AMX}"] == AMX.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and error and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "PBS shouldn't emit validation metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + } + + def "PBS shouldn't discard bid for amx bidder same seat in response as seat in bid.ext.bidderCode"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: bidderCode) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response should contain seat" + assert response.seatbid.seat == [bidderCode] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${bidderCode}"] + assert targeting["hb_size_${bidderCode}"] + assert targeting["hb_bidder"] == bidderCode.value + assert targeting["hb_bidder_${bidderCode}"] == bidderCode.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and error and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "PBS shouldn't emit validation metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + bidderCode << [AMX, AMX_CAMEL_CASE] + } + + def "PBS should discard bid for amx bidder when imp[].bidder isn't same as in bid.ext.bidderCode"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: bidderName) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response shouldn't seat bid" + assert response.seatbid.isEmpty() + + and: "Response should seatNon bid with code 300" + assert response.ext.seatnonbid.size() == 1 + + def seatNonBid = response.ext.seatnonbid[0] + assert seatNonBid.seat == AMX.value + assert seatNonBid.nonBid[0].impId == bidRequest.imp[0].id + assert seatNonBid.nonBid[0].statusCode == RESPONSE_REJECTED_GENERAL + + and: "Response should contain error" + def error = response.ext?.errors[ErrorType.AMX][0] + assert error.code == 5 + assert error.message == ERROR_BID_CODE_VALIDATION + .formatted(bidResponse.seatbid[0].bid[0].id, bidderName, AMX, bidRequest.accountId) + + and: "PBS should emit logs" + def logs = pbsServiceWithAmxBidder.getLogsByValue(bidRequest.accountId) + assert logs.contains(INVALID_BIDDER_CODE_LOGS.formatted(bidderName, AMX, bidRequest.accountId)) + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "PBS should emit metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + bidderName << [BOGUS, UNKNOWN, WILDCARD] + } + + def "PBS should discard bid amx alias requested when imp[].bidder isn't same as in bid.ext.bidderCode"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidder().tap { + imp[0].ext.prebid.bidder.alias = new Generic() + imp[0].ext.prebid.bidder.amx = null + ext.prebid.aliases = [(ALIAS.value): AMX] + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: bidderName) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response shouldn't seat bid" + assert response.seatbid.isEmpty() + + and: "Response should seatNon bid with code 300" + assert response.ext.seatnonbid.size() == 1 + + def seatNonBid = response.ext.seatnonbid[0] + assert seatNonBid.seat == ALIAS.value + assert seatNonBid.nonBid[0].impId == bidRequest.imp[0].id + assert seatNonBid.nonBid[0].statusCode == RESPONSE_REJECTED_GENERAL + + and: "Response should contain error" + def error = response.ext?.errors[ErrorType.ALIAS][0] + assert error.code == 5 + assert error.message == ERROR_BID_CODE_VALIDATION + .formatted(bidResponse.seatbid[0].bid[0].id, bidderName, ALIAS, bidRequest.accountId) + + and: "PBS should emit logs" + def logs = pbsServiceWithAmxBidder.getLogsByValue(bidRequest.accountId) + assert logs.contains(INVALID_BIDDER_CODE_LOGS.formatted(bidderName, ALIAS, bidRequest.accountId)) + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "PBS should emit validation metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(ALIAS)] + + where: + bidderName << [BOGUS, UNKNOWN, WILDCARD] + } + + def "PBS shouldn't discard bid amx alias requested when imp[].bidder is same as in bid.ext.bidderCode and alternate bidder code allow"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + imp[0].ext.prebid.bidder.alias = new Generic() + imp[0].ext.prebid.bidder.amx = null + ext.prebid.aliases = [(ALIAS.value): AMX] + ext.prebid.alternateBidderCodes = requestAlternateBidderCode + } + + and: "Save account config into DB with alternate bidder codes" + def account = getAccountWithAlternateBidderCode(bidRequest).tap { + config.alternateBidderCodes = accountAlternateBidderCodes + } + accountDao.save(account) + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response should contain exp data" + assert response.seatbid.seat == [GENERIC] + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and error and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "PBS shouldn't emit validation metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(ALIAS)] + + where: + requestAlternateBidderCode | accountAlternateBidderCodes + new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) | null + null | new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) + } + + def "PBS shouldn't discard bid amx alias requested when imp[].bidder is same as in bid.ext.bidderCode"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidder().tap { + imp[0].ext.prebid.bidder.alias = new Generic() + imp[0].ext.prebid.bidder.amx = null + ext.prebid.aliases = [(ALIAS.value): AMX] + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: bidderCode) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response should contain exp data" + assert response.seatbid.seat == [bidderCode] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${bidderCode}"] + assert targeting["hb_size_${bidderCode}"] + assert targeting["hb_bidder"] == bidderCode.value + assert targeting["hb_bidder_${bidderCode}"] == bidderCode.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and error and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "PBS shouldn't emit validation metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(bidderCode)] + + where: + bidderCode << [ALIAS, ALIAS_CAMEL_CASE] + } + + def "PBS shouldn't discard the bid or emit a response warning when account alternate bidder codes not fully configured"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Save account config into DB with alternate bidder codes" + def account = getAccountWithAlternateBidderCode(bidRequest).tap { + config.alternateBidderCodes = accountAlternateBidderCodes + } + accountDao.save(account) + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: AMX) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == AMX + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${AMX}"] + assert targeting["hb_size_${AMX}"] + assert targeting["hb_bidder"] == AMX.value + assert targeting["hb_bidder_${AMX}"] == AMX.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings,errors and seatnonbid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Metric shouldn't be updated" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + accountAlternateBidderCodes << [null, + new AlternateBidderCodes(), + new AlternateBidderCodes(enabled: true), + new AlternateBidderCodes(enabled: false), + new AlternateBidderCodes(bidders: [(AMX): new BidderConfig()]), + new AlternateBidderCodes(bidders: [(UNKNOWN): new BidderConfig()]), + new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig()]), + new AlternateBidderCodes(enabled: true, bidders: [(UNKNOWN): new BidderConfig()]), + new AlternateBidderCodes(enabled: false, bidders: [(UNKNOWN): new BidderConfig()]), + new AlternateBidderCodes(enabled: false, bidders: [(AMX): new BidderConfig()]), + new AlternateBidderCodes(bidders: [(AMX): new BidderConfig(enabled: false, allowedBidderCodes: [UNKNOWN])]), + new AlternateBidderCodes(bidders: [(UNKNOWN): new BidderConfig(enabled: false, allowedBidderCodes: [AMX])]), + new AlternateBidderCodes(enabled: false, bidders: [(AMX): new BidderConfig(enabled: false, allowedBidderCodes: [UNKNOWN])]), + new AlternateBidderCodes(enabled: false, bidders: [(UNKNOWN): new BidderConfig(enabled: false, allowedBidderCodes: [AMX])]), + new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: false, allowedBidderCodes: [UNKNOWN])]), + new AlternateBidderCodes(enabled: true, bidders: [(UNKNOWN): new BidderConfig(enabled: false, allowedBidderCodes: [AMX])])] + } + + def "PBS shouldn't discard the bid or emit a response warning when request alternate bidder codes not fully configured"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + ext.prebid.alternateBidderCodes = requestedAlternateBidderCodes + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: AMX) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == AMX + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${AMX}"] + assert targeting["hb_size_${AMX}"] + assert targeting["hb_bidder"] == AMX.value + assert targeting["hb_bidder_${AMX}"] == AMX.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings,errors and seatnonbid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Metric shouldn't be updated" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + requestedAlternateBidderCodes << [null, + new AlternateBidderCodes(), + new AlternateBidderCodes(enabled: true), + new AlternateBidderCodes(enabled: false), + new AlternateBidderCodes(bidders: [(AMX): new BidderConfig()]), + new AlternateBidderCodes(bidders: [(UNKNOWN): new BidderConfig()]), + new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig()]), + new AlternateBidderCodes(enabled: true, bidders: [(UNKNOWN): new BidderConfig()]), + new AlternateBidderCodes(enabled: false, bidders: [(UNKNOWN): new BidderConfig()]), + new AlternateBidderCodes(enabled: false, bidders: [(AMX): new BidderConfig()]), + new AlternateBidderCodes(bidders: [(AMX): new BidderConfig(enabled: false, allowedBidderCodes: [UNKNOWN])]), + new AlternateBidderCodes(bidders: [(UNKNOWN): new BidderConfig(enabled: false, allowedBidderCodes: [AMX])]), + new AlternateBidderCodes(enabled: false, bidders: [(AMX): new BidderConfig(enabled: false, allowedBidderCodes: [UNKNOWN])]), + new AlternateBidderCodes(enabled: false, bidders: [(UNKNOWN): new BidderConfig(enabled: false, allowedBidderCodes: [AMX])]), + new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: false, allowedBidderCodes: [UNKNOWN])]), + new AlternateBidderCodes(enabled: true, bidders: [(UNKNOWN): new BidderConfig(enabled: false, allowedBidderCodes: [AMX])])] + } + + def "PBS shouldn't discard bid when alternate bidder code allows bidder codes fully configured and bidder requested in uppercase"() { + given: "Default bid request with AMX bidder" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + imp[0].ext.prebid.bidder.tap { + amxUpperCase = new Amx() + amx = null + } + ext.prebid.alternateBidderCodes.bidders[AMX].allowedBidderCodesLowerCase = [GENERIC] + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == GENERIC + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response shouldn't contain warnings,errors and seatnonbid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "Metric shouldn't be updated" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + } + + def "PBS shouldn't discard bid when alternate bidder code allows bidder codes fully configured with different case"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Save account config into DB with alternate bidder codes" + def account = getAccountWithAlternateBidderCode(bidRequest).tap { + config = configAccountAlternateBidderCodes + } + accountDao.save(account) + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == GENERIC + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings,errors and seatnonbid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Metric shouldn't be updated" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + configAccountAlternateBidderCodes << [ + new AccountConfig(alternateBidderCodesSnakeCase: new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodesSnakeCase: [GENERIC])])), + new AccountConfig(alternateBidderCodes: new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodesSnakeCase: [GENERIC])])), + new AccountConfig(alternateBidderCodesSnakeCase: new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]))] + } + + def "PBS should take precede of request and discard the bid and emit a response error when alternate bidder codes enabled and bidder came with different bidder code"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode() + + and: "Save account config into DB with alternate bidder codes" + def account = getAccountWithAlternateBidderCode(bidRequest).tap { + config.alternateBidderCodes.bidders[AMX].allowedBidderCodes = [UNKNOWN] + } + accountDao.save(account) + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: UNKNOWN) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response shouldn't seat bid" + assert response.seatbid.isEmpty() + + and: "Response should seatNon bid with code 300" + assert response.ext.seatnonbid.size() == 1 + + def seatNonBid = response.ext.seatnonbid[0] + assert seatNonBid.seat == AMX.value + assert seatNonBid.nonBid[0].impId == bidRequest.imp[0].id + assert seatNonBid.nonBid[0].statusCode == RESPONSE_REJECTED_GENERAL + + and: "Response should contain error" + def error = response.ext?.errors[ErrorType.AMX][0] + assert error.code == 5 + assert error.message == ERROR_BID_CODE_VALIDATION + .formatted(bidResponse.seatbid[0].bid[0].id, UNKNOWN, AMX, bidRequest.accountId) + + and: "PBS should emit logs" + def logs = pbsServiceWithAmxBidder.getLogsByValue(bidRequest.accountId) + assert logs.contains(INVALID_BIDDER_CODE_LOGS.formatted(UNKNOWN, AMX, bidRequest.accountId)) + + and: "PBS should emit metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + } + + def "PBS should discard the bid and emit a response warning when alternate bidder codes disabled and bidder came with different bidderCode"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + ext.prebid.alternateBidderCodes.enabled = requestedAlternateBidderCodes + } + + and: "Save account config into DB with alternate bidder codes" + def account = getAccountWithAlternateBidderCode(bidRequest).tap { + config.alternateBidderCodes.enabled = accountAlternateBidderCodes + } + accountDao.save(account) + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: UNKNOWN) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response shouldn't seat bid" + assert response.seatbid.isEmpty() + + and: "Response should seatNon bid with code 300" + assert response.ext.seatnonbid.size() == 1 + + def seatNonBid = response.ext.seatnonbid[0] + assert seatNonBid.seat == AMX.value + assert seatNonBid.nonBid[0].impId == bidRequest.imp[0].id + assert seatNonBid.nonBid[0].statusCode == RESPONSE_REJECTED_GENERAL + + and: "Response should contain error" + def error = response.ext?.errors[ErrorType.AMX][0] + assert error.code == 5 + assert error.message == ERROR_BID_CODE_VALIDATION + .formatted(bidResponse.seatbid[0].bid[0].id, UNKNOWN, AMX, bidRequest.accountId) + + and: "PBS should emit logs" + def logs = pbsServiceWithAmxBidder.getLogsByValue(bidRequest.accountId) + assert logs.contains(INVALID_BIDDER_CODE_LOGS.formatted(UNKNOWN, AMX, bidRequest.accountId)) + + and: "PBS should emit metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + where: + requestedAlternateBidderCodes | accountAlternateBidderCodes + false | true + false | false + false | null + null | false + } + + def "PBS shouldn't discard the bid or emit a response warning when account alternate bidder codes are enabled and allowed bidder codes are either a wildcard or empty"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Save account config into DB with alternate bidder codes" + def account = getAccountWithAlternateBidderCode(bidRequest).tap { + config.alternateBidderCodes.bidders[AMX].allowedBidderCodes = accountAllowedBidderCodes + } + accountDao.save(account) + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid.seat.flatten() == [GENERIC] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response shouldn't contain warnings and errors and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "PBs metric shouldn't be updated" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + accountAllowedBidderCodes << [[WILDCARD], [WILDCARD, EMPTY], [EMPTY, WILDCARD], null] + } + + def "PBS shouldn't discard the bid or emit a response warning when request alternate bidder codes are enabled and allowed bidder codes are either a wildcard or empty"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + ext.prebid.alternateBidderCodes.bidders[AMX].allowedBidderCodesLowerCase = requestedAllowedBidderCodes + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid.seat.flatten() == [GENERIC] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and errors and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "PBs metric shouldn't be updated" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + requestedAllowedBidderCodes << [[WILDCARD], [WILDCARD, EMPTY], [EMPTY, WILDCARD], null] + } + + def "PBS shouldn't discard the bid or emit a response warning when request alternate bidder codes are enabled and the allowed bidder codes is same as bidder's request"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + ext.prebid.alternateBidderCodes.bidders = requestAlternateBidders + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid.seat.flatten() == [GENERIC] + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and errors and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "PBs metric shouldn't be updated" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + requestAlternateBidders << [[(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])], + [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC_CAMEL_CASE])], + [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC_CAMEL_CASE])], + [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]] + } + + def "PBS shouldn't discard the bid or emit a response warning when account alternate bidder codes are enabled and the allowed bidder codes is same as bidder's request"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Save account config into DB with alternate bidder codes" + def account = getAccountWithAlternateBidderCode(bidRequest).tap { + config.alternateBidderCodes.bidders = accountAlternateBidders + } + accountDao.save(account) + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid.seat.flatten() == [GENERIC] + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Response shouldn't contain warnings and errors and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "PBs metric shouldn't be updated" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + accountAlternateBidders << [[(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])], + [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC_CAMEL_CASE])], + [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC_CAMEL_CASE])], + [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]] + } + + def "PBS shouldn't discard the bid or emit a response warning when default account alternate bidder codes are enabled and the allowed bidder codes match the bidder's request"() { + given: "Pbs config with default-account-config of alternate bidder code" + def defaultAccountConfig = AccountConfig.defaultAccountConfig.tap { + alternateBidderCodes = new AlternateBidderCodes().tap { + it.enabled = true + it.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [AMX])] + } + } + def config = AMX_CONFIG + ["settings.default-account-config": encode(defaultAccountConfig)] + def pbsService = pbsServiceFactory.getService(config) + + and: "Default bid request" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + ext.prebid.alternateBidderCodes = null + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: AMX) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsService) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response should contain seatbid.seat" + assert response.seatbid.seat.flatten() == [AMX] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${AMX}"] + assert targeting["hb_size_${AMX}"] + assert targeting["hb_bidder"] == AMX.value + assert targeting["hb_bidder_${AMX}"] == AMX.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and errors and seatnonbid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "Alert.general metric shouldn't be updated" + def metrics = pbsService.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(config) + } + + def "PBS should discard the bid and emit a response warning when request alternate bidder codes are enabled and the allowed bidder codes doesn't match the bidder's request"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode() + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: requestedAllowedBidderCode) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response shouldn't seat bid" + assert response.seatbid.isEmpty() + + and: "Response should seatNon bid with code 300" + assert response.ext.seatnonbid.size() == 1 + + def seatNonBid = response.ext.seatnonbid[0] + assert seatNonBid.seat == AMX.value + assert seatNonBid.nonBid[0].impId == bidRequest.imp[0].id + assert seatNonBid.nonBid[0].statusCode == RESPONSE_REJECTED_GENERAL + + and: "Response should contain error" + def error = response.ext?.errors[ErrorType.AMX][0] + assert error.code == 5 + assert error.message == ERROR_BID_CODE_VALIDATION + .formatted(bidResponse.seatbid[0].bid[0].id, requestedAllowedBidderCode, AMX, bidRequest.accountId) + + and: "PBS should emit logs" + def logs = pbsServiceWithAmxBidder.getLogsByValue(bidRequest.accountId) + assert logs.contains(INVALID_BIDDER_CODE_LOGS.formatted(requestedAllowedBidderCode, AMX, bidRequest.accountId)) + + and: "PBS should emit metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + where: + requestedAllowedBidderCode << [UNKNOWN, BOGUS] + } + + def "PBS should discard the bid and emit a response warning when account alternate bidder codes are enabled and the allowed bidder codes doesn't match the bidder's request"() { + given: "Default bid request with alternate bidder codes" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Save account config into DB with alternate bidder codes" + def account = getAccountWithAlternateBidderCode(bidRequest) + accountDao.save(account) + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: requestedAllowedBidderCode) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response shouldn't seat bid" + assert response.seatbid.isEmpty() + + and: "Response should seatNon bid with code 300" + assert response.ext.seatnonbid.size() == 1 + + def seatNonBid = response.ext.seatnonbid[0] + assert seatNonBid.seat == AMX.value + assert seatNonBid.nonBid[0].impId == bidRequest.imp[0].id + assert seatNonBid.nonBid[0].statusCode == RESPONSE_REJECTED_GENERAL + + and: "Response should contain error" + def error = response.ext?.errors[ErrorType.AMX][0] + assert error.code == 5 + assert error.message == ERROR_BID_CODE_VALIDATION + .formatted(bidResponse.seatbid[0].bid[0].id, requestedAllowedBidderCode, AMX, bidRequest.accountId) + + and: "PBS should emit logs" + def logs = pbsServiceWithAmxBidder.getLogsByValue(bidRequest.accountId) + assert logs.contains(INVALID_BIDDER_CODE_LOGS.formatted(requestedAllowedBidderCode, AMX, bidRequest.accountId)) + + and: "PBS should emit metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + where: + requestedAllowedBidderCode << [UNKNOWN, BOGUS] + } + + def "PBS should discard the bid and emit a response warning when default account alternate bidder codes are enabled and the allowed bidder codes doesn't match the bidder's request"() { + given: "Pbs config with default-account-config" + def defaultAccountConfig = AccountConfig.defaultAccountConfig.tap { + alternateBidderCodes = new AlternateBidderCodes().tap { + it.enabled = true + it.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [AMX])] + } + } + def pbsConfig = AMX_CONFIG + ["settings.default-account-config": encode(defaultAccountConfig)] + def pbsService = pbsServiceFactory.getService(pbsConfig) + + and: "Default bid request" + def bidRequest = getBidRequestWithAmxBidder() + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: allowedBidderCodes) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsService) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Bid response shouldn't seat bid" + assert response.seatbid.isEmpty() + + and: "Response should seatNon bid with code 300" + assert response.ext.seatnonbid.size() == 1 + + def seatNonBid = response.ext.seatnonbid[0] + assert seatNonBid.seat == AMX.value + assert seatNonBid.nonBid[0].impId == bidRequest.imp[0].id + assert seatNonBid.nonBid[0].statusCode == RESPONSE_REJECTED_GENERAL + + and: "Response should contain error" + def error = response.ext?.errors[ErrorType.AMX][0] + assert error.code == 5 + assert error.message == ERROR_BID_CODE_VALIDATION + .formatted(bidResponse.seatbid[0].bid[0].id, allowedBidderCodes, AMX, bidRequest.accountId) + + and: "PBS should emit logs" + def logs = pbsService.getLogsByValue(bidRequest.accountId) + assert logs.contains(INVALID_BIDDER_CODE_LOGS.formatted(allowedBidderCodes, AMX, bidRequest.accountId)) + + and: "Response shouldn't contain demand source" + assert !response?.seatbid?.bid?.ext?.prebid?.meta?.demandSource + + and: "PBS should emit metrics" + def metrics = pbsService.sendCollectedMetricsRequest() + assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + + where: + allowedBidderCodes << [BOGUS, UNKNOWN] + } + + def "PBS shouldn't discard bid when hard alias and alternate bidder allow bidder code"() { + given: "PBS config with bidder" + def pbsConfig = AMX_CONFIG + ["adapters.amx.aliases.alias.enabled" : "true", + "adapters.amx.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString()] + def defaultPbsService = pbsServiceFactory.getService(pbsConfig) + + and: "Default bid request with alias" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + imp[0].ext.prebid.bidder.tap { + amx = null + alias = new Generic() + } + ext.prebid.alternateBidderCodes.bidders = [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])] + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [ALIAS] + + and: "Response should contain seat bid" + assert response.seatbid.seat == [GENERIC] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "PBS shouldn't emit validation metrics" + def metrics = defaultPbsService.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + } + + def "PBS shouldn't discard bid when alternate bidder code allow and soft alias with case"() { + given: "Default bid request with amx bidder" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + imp[0].ext.prebid.bidder.aliasUpperCase = new Generic() + imp[0].ext.prebid.bidder.amx = null + ext.prebid.aliases = [(ALIAS.value): AMX] + ext.prebid.alternateBidderCodes = requestAlternateBidderCode + } + + and: "Save account config into DB with alternate bidder codes" + def account = getAccountWithAlternateBidderCode(bidRequest).tap { + config.alternateBidderCodes = accountAlternateBidderCodes + } + accountDao.save(account) + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + and: "Flash metrics" + flushMetrics(pbsServiceWithAmxBidder) + + when: "PBS processes auction request" + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Bid response should contain exp data" + assert response.seatbid.seat == [GENERIC] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Response shouldn't contain warnings and error and seatNonBid" + assert !response.ext?.warnings + assert !response.ext?.errors + assert !response.ext?.seatnonbid + + and: "PBS shouldn't emit validation metrics" + def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(ALIAS)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + + where: + requestAlternateBidderCode | accountAlternateBidderCodes + new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) | null + null | new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) + } + + def "PBS should populate adapter code with requested bidder when conflict soft and hard alias and alternate bidder code"() { + given: "PBS config with bidder" + def pbsConfig = AMX_CONFIG + ["adapters.amx.aliases.alias.enabled" : "true", + "adapters.amx.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString()] + def defaultPbsService = pbsServiceFactory.getService(pbsConfig) + + and: "Bid request with amx bidder and targeting" + def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { + imp[0].ext.prebid.bidder.alias = new Generic() + imp[0].ext.prebid.bidder.amx = null + imp[0].ext.prebid.bidder.generic = null + it.ext.prebid.aliases = [(ALIAS.value): GENERIC] + it.ext.prebid.alternateBidderCodes.bidders = [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodesLowerCase: [GENERIC])] + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [ALIAS] + + and: "Response should contain seat bid" + assert response.seatbid.seat == [GENERIC] + + and: "Response shouldn't contain demand source" + assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC}"] + assert targeting["hb_size_${GENERIC}"] + assert targeting["hb_bidder"] == GENERIC.value + assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "PBS shouldn't emit validation metrics" + def metrics = defaultPbsService.sendCollectedMetricsRequest() + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + } + + private static Account getAccountWithAlternateBidderCode(BidRequest bidRequest) { + new Account().tap { + it.uuid = bidRequest.accountId + it.config = new AccountConfig(status: ACTIVE, alternateBidderCodes: new AlternateBidderCodes().tap { + it.enabled = true + it.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [AMX])] + }) + } + } + + private static BidRequest getBidRequestWithAmxBidderAndAlternateBidderCode() { + getBidRequestWithAmxBidder().tap { + it.ext.prebid.alternateBidderCodes = new AlternateBidderCodes().tap { + enabled = true + bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodesLowerCase: [AMX])] + } + } + } + + private static BidRequest getBidRequestWithAmxBidder() { + BidRequest.defaultBidRequest.tap { + it.imp[0].ext.prebid.bidder.tap { + generic = null + amx = new Amx() + } + ext.prebid.tap { + returnAllBidStatus = true + targeting = new Targeting() + } + } + } +} diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy index 79eb960787f..d4fd06cad64 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy @@ -3,10 +3,13 @@ package org.prebid.server.functional.tests import org.prebid.server.functional.model.Currency import org.prebid.server.functional.model.config.AccountAuctionConfig import org.prebid.server.functional.model.config.AccountConfig +import org.prebid.server.functional.model.config.AlternateBidderCodes +import org.prebid.server.functional.model.config.BidderConfig import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.mock.services.currencyconversion.CurrencyConversionRatesResponse import org.prebid.server.functional.model.request.auction.AdjustmentRule import org.prebid.server.functional.model.request.auction.AdjustmentType +import org.prebid.server.functional.model.request.auction.Amx import org.prebid.server.functional.model.request.auction.BidAdjustment import org.prebid.server.functional.model.request.auction.BidAdjustmentFactors import org.prebid.server.functional.model.request.auction.BidAdjustmentRule @@ -14,6 +17,7 @@ import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Imp import org.prebid.server.functional.model.request.auction.VideoPlacementSubtypes import org.prebid.server.functional.model.request.auction.VideoPlcmtSubtype +import org.prebid.server.functional.model.response.auction.BidExt import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService @@ -27,6 +31,7 @@ import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST import static org.prebid.server.functional.model.Currency.EUR import static org.prebid.server.functional.model.Currency.GBP import static org.prebid.server.functional.model.Currency.USD +import static org.prebid.server.functional.model.bidder.BidderName.AMX import static org.prebid.server.functional.model.bidder.BidderName.APPNEXUS import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.bidder.BidderName.RUBICON @@ -68,7 +73,9 @@ class BidAdjustmentSpec extends BaseSpec { private static final CurrencyConversion currencyConversion = new CurrencyConversion(networkServiceContainer).tap { setCurrencyConversionRatesResponse(CurrencyConversionRatesResponse.getDefaultCurrencyConversionRatesResponse(DEFAULT_CURRENCY_RATES)) } - private static final PrebidServerService pbsService = pbsServiceFactory.getService(externalCurrencyConverterConfig) + private static final Map AMX_CONFIG = ["adapters.amx.enabled" : "true", + "adapters.amx.endpoint": "$networkServiceContainer.rootUri/auction".toString()] + private static final PrebidServerService pbsService = pbsServiceFactory.getService(externalCurrencyConverterConfig + AMX_CONFIG) def "PBS should adjust bid price for matching bidder when request has per-bidder bid adjustment factors"() { given: "Default bid request with bid adjustment" @@ -1074,6 +1081,71 @@ class BidAdjustmentSpec extends BaseSpec { adjustmentType << [CPM, STATIC] } + def "PBS should adjust bid price for matching bidder and alternate bidder code when request has per-bidder bid adjustment factors"() { + given: "Default bid request with bid adjustment and amx bidder" + def bidRequest = BidRequest.getDefaultBidRequest(SITE).tap { + imp[0].ext.prebid.bidder.generic = null + imp[0].ext.prebid.bidder.amx = new Amx() + it.ext.prebid.tap { + alternateBidderCodes = new AlternateBidderCodes().tap { + enabled = true + bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])] + } + bidAdjustmentFactors = new BidAdjustmentFactors(adjustments: [(GENERIC): bidAdjustmentFactor]) + } + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Final bid price should be adjusted" + assert response?.seatbid?.first?.bid?.first?.price == bidResponse.seatbid.first.bid.first.price * + bidAdjustmentFactor + + where: + bidAdjustmentFactor << [0.9, 1.1] + } + + def "PBS should prefer bid price adjustment based on media type and alternate bidder code when request has per-media-type bid adjustment factors"() { + given: "Default bid request with bid adjustment" + def bidRequest = BidRequest.getDefaultBidRequest(SITE).tap { + imp[0].ext.prebid.bidder.generic = null + imp[0].ext.prebid.bidder.amx = new Amx() + ext.prebid.tap { + bidAdjustmentFactors = new BidAdjustmentFactors().tap { + adjustments = [(GENERIC): randomDecimal] + mediaTypes = [(BANNER): [(GENERIC): bidAdjustmentFactor]] + } + alternateBidderCodes = new AlternateBidderCodes().tap { + enabled = true + bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])] + } + } + } + + and: "Bid response with bidder code" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Final bid price should be adjusted" + assert response?.seatbid?.first?.bid?.first?.price == bidResponse.seatbid.first.bid.first.price * + bidAdjustmentFactor + + where: + bidAdjustmentFactor << [0.9, 1.1] + } + private static Map getExternalCurrencyConverterConfig() { ["auction.ad-server-currency" : DEFAULT_CURRENCY as String, "currency-converter.external-rates.enabled" : "true", 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 e8151762026..5269d31b977 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy @@ -7,6 +7,7 @@ import org.prebid.server.functional.model.db.StoredImp import org.prebid.server.functional.model.db.StoredRequest import org.prebid.server.functional.model.request.amp.AmpRequest import org.prebid.server.functional.model.request.auction.Adrino +import org.prebid.server.functional.model.request.auction.Amx import org.prebid.server.functional.model.request.auction.AuctionEnvironment import org.prebid.server.functional.model.request.auction.Banner import org.prebid.server.functional.model.request.auction.BidRequest @@ -22,10 +23,12 @@ 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.auction.Targeting import org.prebid.server.functional.model.request.vtrack.VtrackRequest import org.prebid.server.functional.model.request.vtrack.xml.Vast import org.prebid.server.functional.model.response.auction.Adm import org.prebid.server.functional.model.response.auction.Bid +import org.prebid.server.functional.model.response.auction.BidExt import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.CcpaConsent @@ -34,7 +37,12 @@ import static org.prebid.server.functional.model.Currency.CHF import static org.prebid.server.functional.model.Currency.EUR import static org.prebid.server.functional.model.Currency.JPY import static org.prebid.server.functional.model.Currency.USD +import static org.prebid.server.functional.model.bidder.BidderName.ALIAS +import static org.prebid.server.functional.model.bidder.BidderName.ALIAS_UPPER_CASE +import static org.prebid.server.functional.model.bidder.BidderName.AMX import static org.prebid.server.functional.model.bidder.BidderName.APPNEXUS +import static org.prebid.server.functional.model.bidder.BidderName.GENERIC_CAMEL_CASE +import static org.prebid.server.functional.model.bidder.BidderName.OPENX import static org.prebid.server.functional.model.bidder.CompressionType.GZIP import static org.prebid.server.functional.model.bidder.CompressionType.NONE import static org.prebid.server.functional.model.request.auction.Asset.titleAsset @@ -1026,9 +1034,10 @@ class BidderParamsSpec extends BaseSpec { def "PBS should send request to bidder when adapters.bidder.aliases.bidder.meta-info.currency-accepted not specified"() { given: "PBS with adapter configuration" - 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 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" @@ -1145,9 +1154,10 @@ class BidderParamsSpec extends BaseSpec { 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 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 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" @@ -1189,9 +1199,10 @@ class BidderParamsSpec extends BaseSpec { 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 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 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" @@ -1361,4 +1372,345 @@ class BidderParamsSpec extends BaseSpec { and: "targeting should be empty" assert response.seatbid.isEmpty() } + + def "PBS should send bidder code from imp[].ext.prebid.bidder to seatbid.bid.ext.prebid.meta.adapterCode"() { + given: "Default basic bid request" + def bidRequest = BidRequest.defaultBidRequest + + and: "Default bid response" + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + seatbid[0].seat = OPENX + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.GENERIC] + + and: "Bidder request should be valid" + assert bidder.getBidderRequest(bidRequest.id) + } + + def "PBS should send bidder code from imp[].ext.prebid.bidder to seatbid.bid.ext.prebid.meta.adapterCode when requested soft alias"() { + given: "Default bid request with alias" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].ext.prebid.bidder.tap { + generic = null + alias = new Generic() + } + ext.prebid.aliases = [(ALIAS.value): BidderName.GENERIC] + ext.prebid.targeting = new Targeting() + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.GENERIC] + + and: "Response should contain seat bid" + assert response.seatbid.seat == [BidderName.ALIAS] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${BidderName.ALIAS}"] + assert targeting["hb_size_${BidderName.ALIAS}"] + assert targeting["hb_bidder"] == BidderName.ALIAS.value + assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + } + + def "PBS should populate same code for adapter code when make call for generic hard code alias"() { + given: "PBS config with bidder" + def pbsConfig = ["adapters.generic.aliases.alias.enabled" : "true", + "adapters.generic.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString()] + def defaultPbsService = pbsServiceFactory.getService(pbsConfig) + + and: "Default bid request with alias" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].ext.prebid.bidder.tap { + generic = null + alias = new Generic() + } + ext.prebid.targeting = new Targeting() + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.ALIAS] + + and: "Response should contain seat bid" + assert response.seatbid.seat == [BidderName.ALIAS] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${BidderName.ALIAS}"] + assert targeting["hb_size_${BidderName.ALIAS}"] + assert targeting["hb_bidder"] == BidderName.ALIAS.value + assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + } + + def "PBS should make call for alias when hard alias and demandSource specified"() { + given: "PBS config with bidder" + def pbsConfig = ["adapters.amx.enabled" : "true", + "adapters.amx.endpoint" : "$networkServiceContainer.rootUri/auction".toString(), + "adapters.amx.aliases.alias.enabled" : "true", + "adapters.amx.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString()] + def defaultPbsService = pbsServiceFactory.getService(pbsConfig) + + and: "Default bid Request with generic and openx bidder within separate imps" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].ext.prebid.bidder.tap { + generic = null + alias = new Generic() + } + ext.prebid.targeting = new Targeting() + } + + and: "Bid response with bidder code" + def demandSource = PBSUtils.randomString + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, BidderName.ALIAS).tap { + it.seatbid[0].bid[0].ext = new BidExt(demandSource: demandSource) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain demand source" + assert response.seatbid.bid.ext.prebid.meta.demandSource.flatten() == [demandSource] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.ALIAS] + + and: "Response should contain seat bid" + assert response.seatbid.seat == [BidderName.ALIAS] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${BidderName.ALIAS}"] + assert targeting["hb_size_${BidderName.ALIAS}"] + assert targeting["hb_bidder"] == BidderName.ALIAS.value + assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + } + + def "PBS should send bidder code from imp[].ext.prebid.bidder to seatbid.bid.ext.prebid.meta.adapterCode when requested soft alias with upper case"() { + given: "Default bid request with alias" + def bidRequest = BidRequest.defaultBidRequest.tap { + ext.prebid.aliases = [(ALIAS.value): BidderName.GENERIC] + ext.prebid.targeting = new Targeting() + imp[0].ext.prebid.bidder.tap { + generic = null + aliasUpperCase = new Generic() + } + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.GENERIC] + + and: "Response should contain seat bid" + assert response.seatbid.seat == [ALIAS_UPPER_CASE] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${ALIAS_UPPER_CASE}"] + assert targeting["hb_size_${ALIAS_UPPER_CASE}"] + assert targeting["hb_bidder"] == ALIAS_UPPER_CASE.value + assert targeting["hb_bidder_${ALIAS_UPPER_CASE}"] == ALIAS_UPPER_CASE.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + } + + def "PBS should populate targeting with bidder in camel case when bidder with camel case was requested"() { + given: "Default bid request" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].ext.prebid.bidder.generic = null + imp[0].ext.prebid.bidder.genericCamelCase = new Generic() + it.ext.prebid.targeting = new Targeting() + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${GENERIC_CAMEL_CASE}"] + assert targeting["hb_size_${GENERIC_CAMEL_CASE}"] + assert targeting["hb_bidder"] == GENERIC_CAMEL_CASE.value + assert targeting["hb_bidder_${GENERIC_CAMEL_CASE}"] == GENERIC_CAMEL_CASE.value + + and: "Bid response should contain seat" + assert response.seatbid.seat == [GENERIC_CAMEL_CASE] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.GENERIC] + } + + def "PBS should make call for alias in upper case when soft alias specified with same name in upper case strategy"() { + given: "Default bid request with soft alias and targeting" + def bidRequest = BidRequest.defaultBidRequest.tap { + ext.prebid.aliases = [(ALIAS.value): BidderName.GENERIC] + imp[0].ext.prebid.bidder.aliasUpperCase = new Generic() + imp[0].ext.prebid.bidder.generic = null + it.ext.prebid.targeting = new Targeting() + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.GENERIC] + + and: "Response should contain seat bid" + assert response.seatbid.seat == [ALIAS_UPPER_CASE] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${ALIAS_UPPER_CASE}"] + assert targeting["hb_size_${ALIAS_UPPER_CASE}"] + assert targeting["hb_bidder"] == ALIAS_UPPER_CASE.value + assert targeting["hb_bidder_${ALIAS_UPPER_CASE}"] == ALIAS_UPPER_CASE.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + } + + def "PBS should populate adapter code with requested bidder when conflict with soft and hard alias"() { + given: "PBS config with bidder" + def pbsConfig = ["adapters.amx.enabled" : "true", + "adapters.amx.endpoint" : "$networkServiceContainer.rootUri/auction".toString(), + "adapters.amx.aliases.alias.enabled" : "true", + "adapters.amx.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString()] + def defaultPbsService = pbsServiceFactory.getService(pbsConfig) + + and: "Bid request with amx bidder and targeting" + def bidRequest = BidRequest.getDefaultBidRequest().tap { + imp[0].ext.prebid.bidder.alias = new Generic() + imp[0].ext.prebid.bidder.amx = null + imp[0].ext.prebid.bidder.generic = null + it.ext.prebid.aliases = [(ALIAS.value): BidderName.GENERIC] + it.ext.prebid.targeting = new Targeting() + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.ALIAS] + + and: "Response should contain seat bid" + assert response.seatbid.seat == [BidderName.ALIAS] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${BidderName.ALIAS}"] + assert targeting["hb_size_${BidderName.ALIAS}"] + assert targeting["hb_bidder"] == BidderName.ALIAS.value + assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + } + + def "PBS should populate adapter code with requested bidder when conflict with soft and generic hard alias"() { + given: "PBS config with bidders" + def pbsConfig = ["adapters.amx.enabled" : "true", + "adapters.amx.endpoint" : "$networkServiceContainer.rootUri/auction".toString(), + "adapters.generic.aliases.alias.enabled" : "true", + "adapters.generic.aliases.alias.endpoint": "$networkServiceContainer.rootUri/auction".toString()] + def defaultPbsService = pbsServiceFactory.getService(pbsConfig) + + and: "Bid request with amx bidder and targeting" + def bidRequest = BidRequest.getDefaultBidRequest().tap { + imp[0].ext.prebid.bidder.alias = new Generic() + imp[0].ext.prebid.bidder.amx = null + imp[0].ext.prebid.bidder.generic = null + it.ext.prebid.aliases = [(ALIAS.value): AMX] + it.ext.prebid.targeting = new Targeting() + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.ALIAS] + + and: "Response should contain seat bid" + assert response.seatbid.seat == [BidderName.ALIAS] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${BidderName.ALIAS}"] + assert targeting["hb_size_${BidderName.ALIAS}"] + assert targeting["hb_bidder"] == BidderName.ALIAS.value + assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + } + + def "PBS should properly populate bidder code when soft alias ignore standalone adapter"() { + given: "PBS config with amx bidder" + def pbsConfig = ["adapters.amx.enabled" : "true", + "adapters.amx.endpoint": "$networkServiceContainer.rootUri/auction".toString()] + def defaultPbsService = pbsServiceFactory.getService(pbsConfig) + + and: "Default bid request with soft alias and targeting" + def bidRequest = BidRequest.defaultBidRequest.tap { + imp[0].ext.prebid.bidder.amx = new Amx() + imp[0].ext.prebid.bidder.generic = null + ext.prebid.targeting = new Targeting() + ext.prebid.aliases = [(AMX.value): BidderName.GENERIC] + } + + when: "PBS processes auction request" + def response = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seat" + assert response.seatbid.seat == [AMX] + + and: "Response should contain bidder targeting" + def targeting = response.seatbid[0].bid[0].ext.prebid.targeting + assert targeting["hb_pb_${AMX}"] + assert targeting["hb_size_${AMX}"] + assert targeting["hb_bidder"] == AMX.value + assert targeting["hb_bidder_${AMX}"] == AMX.value + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(pbsConfig) + } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/responsecorrenction/ResponseCorrectionSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/responsecorrenction/ResponseCorrectionSpec.groovy index 1694a17dbaf..b4cbdd3fb88 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/responsecorrenction/ResponseCorrectionSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/responsecorrenction/ResponseCorrectionSpec.groovy @@ -233,7 +233,7 @@ class ResponseCorrectionSpec extends ModuleBaseSpec { assert response.seatbid.bid.ext.prebid.type.flatten() == [mediaType] and: "Response shouldn't contain media type for prebid meta" - assert !response?.seatbid?.bid?.ext?.prebid?.meta?.mediaType?.flatten()?.size() + assert !response?.seatbid?.first?.bid?.first?.ext?.prebid?.meta?.mediaType and: "Response shouldn't contain errors" assert !response.ext.errors @@ -516,7 +516,7 @@ class ResponseCorrectionSpec extends ModuleBaseSpec { assert response.seatbid.bid.ext.prebid.type.flatten() == [VIDEO] and: "Response shouldn't contain media type for prebid meta" - assert !response?.seatbid?.bid?.ext?.prebid?.meta?.mediaType?.flatten()?.size() + assert !response?.seatbid?.first?.bid?.first?.ext?.prebid?.meta?.mediaType and: "Response shouldn't contain errors" assert !response.ext.errors From 1359e61e5993177be544846d1b26b34d67af6e47 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Wed, 19 Mar 2025 12:24:34 +0100 Subject: [PATCH 21/23] Fix tests --- .../connatix/test-banner-auction-connatix-response.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/resources/org/prebid/server/it/openrtb2/connatix/test-banner-auction-connatix-response.json b/src/test/resources/org/prebid/server/it/openrtb2/connatix/test-banner-auction-connatix-response.json index 3d1b37feaad..7c00ed3b4a3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/connatix/test-banner-auction-connatix-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/connatix/test-banner-auction-connatix-response.json @@ -22,7 +22,10 @@ "origbidcpm": 0.3, "origbidcur": "USD", "prebid": { - "type": "banner" + "type": "banner", + "meta": { + "adaptercode": "connatix" + } } } } From 31f1cff8450fe27e9563da245cdaaf2d48ad57b8 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Wed, 19 Mar 2025 13:42:39 +0100 Subject: [PATCH 22/23] Fix comments --- .../server/auction/aliases/AlternateBidderCodesConfig.java | 2 +- .../java/org/prebid/server/auction/aliases/BidderAliases.java | 2 +- .../prebid/server/auction/{ => aliases}/BidderAliasesTest.java | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) rename src/test/java/org/prebid/server/auction/{ => aliases}/BidderAliasesTest.java (99%) diff --git a/src/main/java/org/prebid/server/auction/aliases/AlternateBidderCodesConfig.java b/src/main/java/org/prebid/server/auction/aliases/AlternateBidderCodesConfig.java index 91b619e71c2..0e91f87fe54 100644 --- a/src/main/java/org/prebid/server/auction/aliases/AlternateBidderCodesConfig.java +++ b/src/main/java/org/prebid/server/auction/aliases/AlternateBidderCodesConfig.java @@ -6,5 +6,5 @@ public interface AlternateBidderCodesConfig { Boolean getEnabled(); - Map getBidders(); + Map getBidders(); } diff --git a/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java b/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java index 3b8c18b5ead..6de52b67fbe 100644 --- a/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java +++ b/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java @@ -89,7 +89,7 @@ public boolean isAllowedAlternateBidderCode(String bidder, String alternateBidde return allowedBidderCodes.contains(WILDCARD) || allowedBidderCodes.contains(alternateBidderCode); } - private static Map> resolveAlternateBidderCodes( + private static Map> resolveAlternateBidderCodes( AlternateBidderCodesConfig alternateBidderCodes) { return Optional.ofNullable(alternateBidderCodes) diff --git a/src/test/java/org/prebid/server/auction/BidderAliasesTest.java b/src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java similarity index 99% rename from src/test/java/org/prebid/server/auction/BidderAliasesTest.java rename to src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java index b6adf02682e..2b8fefcde5e 100644 --- a/src/test/java/org/prebid/server/auction/BidderAliasesTest.java +++ b/src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java @@ -1,11 +1,10 @@ -package org.prebid.server.auction; +package org.prebid.server.auction.aliases; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodes; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidAlternateBidderCodesBidder; From 9372e107af4938445670cf90ee21a05c12fde99f Mon Sep 17 00:00:00 2001 From: antonbabak Date: Wed, 19 Mar 2025 16:48:40 +0100 Subject: [PATCH 23/23] Revert Bidadjustments Changes --- .../BidAdjustmentsProcessor.java | 3 - .../BidAdjustmentsResolver.java | 14 +--- .../BidAdjustmentsProcessorTest.java | 24 ++---- .../BidAdjustmentsResolverTest.java | 82 +------------------ 4 files changed, 13 insertions(+), 110 deletions(-) diff --git a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java index b8cc890e44d..e881ba5c487 100644 --- a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java +++ b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java @@ -105,7 +105,6 @@ private BidderBid applyBidAdjustments(BidderBid bidderBid, final Price priceWithAdjustmentsApplied = applyBidAdjustmentRules( priceWithFactorsApplied, bidder, - bidderBid.getSeat(), bidRequest, bidAdjustments, mediaType, @@ -196,7 +195,6 @@ private static BigDecimal adjustPrice(BigDecimal priceAdjustmentFactor, BigDecim private Price applyBidAdjustmentRules(Price bidPrice, String bidder, - String seat, BidRequest bidRequest, BidAdjustments bidAdjustments, ImpMediaType mediaType, @@ -208,7 +206,6 @@ private Price applyBidAdjustmentRules(Price bidPrice, bidAdjustments, mediaType, bidder, - seat, dealId); } } diff --git a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java index 76766aced79..ffac1cbc51a 100644 --- a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java +++ b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java @@ -1,7 +1,6 @@ package org.prebid.server.bidadjustments; import com.iab.openrtb.request.BidRequest; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidadjustments.model.BidAdjustmentType; import org.prebid.server.bidadjustments.model.BidAdjustments; @@ -43,23 +42,14 @@ public Price resolve(Price initialPrice, BidAdjustments bidAdjustments, ImpMediaType targetMediaType, String targetBidder, - String targetSeat, String targetDealId) { - List adjustmentsRules = findRules( + final List adjustmentsRules = findRules( bidAdjustments, targetMediaType, - targetSeat, + targetBidder, targetDealId); - if (CollectionUtils.isEmpty(adjustmentsRules)) { - adjustmentsRules = findRules( - bidAdjustments, - targetMediaType, - targetBidder, - targetDealId); - } - return adjustPrice(initialPrice, adjustmentsRules, bidRequest); } diff --git a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java index 4bf637e7545..15cec732ccf 100644 --- a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java @@ -74,7 +74,7 @@ public class BidAdjustmentsProcessorTest extends VertxTest { public void before() { given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); target = new BidAdjustmentsProcessor( @@ -95,7 +95,7 @@ public void shouldReturnBidsWithUpdatedPriceCurrencyConversionAndAdjusted() { final AuctionParticipation auctionParticipation = givenAuctionParticipation(bidderResponse, bidRequest); final Price adjustedPrice = Price.of("EUR", BigDecimal.valueOf(5.0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willReturn(adjustedPrice); final BigDecimal expectedPrice = new BigDecimal("123.5"); @@ -116,7 +116,6 @@ public void shouldReturnBidsWithUpdatedPriceCurrencyConversionAndAdjusted() { eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), - eq("seat"), eq("dealId")); } @@ -132,7 +131,7 @@ public void shouldReturnSameBidPriceIfNoChangesAppliedToBidPrice() { given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocation -> invocation.getArgument(0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); // when @@ -183,7 +182,7 @@ public void shouldDropBidIfPrebidExceptionWasThrownDuringBidAdjustmentResolving( given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocation -> invocation.getArgument(0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willThrow(new PreBidException("Unable to convert bid currency CUR to desired ad server currency USD")); // when @@ -219,7 +218,7 @@ public void shouldUpdateBidPriceWithCurrencyConversionAndPriceAdjustmentFactorAn given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder", "seat")) .willReturn(BigDecimal.TEN); final Price adjustedPrice = Price.of("EUR", BigDecimal.valueOf(5.0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willReturn(adjustedPrice); final BigDecimal expectedPrice = new BigDecimal("123.5"); given(currencyService.convertCurrency(any(), any(), eq("EUR"), eq("UAH"))).willReturn(expectedPrice); @@ -241,7 +240,6 @@ public void shouldUpdateBidPriceWithCurrencyConversionAndPriceAdjustmentFactorAn eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), - eq("seat"), eq("dealId")); } @@ -380,7 +378,7 @@ public void shouldUpdateBidPriceWithCurrencyConversionForMultipleBid() { .extracting(Bid::getPrice) .containsOnly(bidder3Price, updatedPrice, updatedPrice); - verify(bidAdjustmentsResolver, times(3)).resolve(any(), any(), any(), any(), any(), any(), any()); + verify(bidAdjustmentsResolver, times(3)).resolve(any(), any(), any(), any(), any(), any()); } @Test @@ -419,7 +417,6 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentFactorPresent() { eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), - eq("seat"), eq("dealId")); } @@ -472,7 +469,6 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP eq(givenBidAdjustments()), eq(ImpMediaType.video_instream), eq("bidder"), - eq("seat"), eq("dealId")); } @@ -525,7 +521,6 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP eq(givenBidAdjustments()), eq(ImpMediaType.video_instream), eq("bidder"), - eq("seat"), eq("dealId")); } @@ -577,7 +572,6 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoOutstreamMediaTypeIfVideo eq(givenBidAdjustments()), eq(ImpMediaType.video_outstream), eq("bidder"), - eq("seat"), eq("dealId")); } @@ -629,7 +623,6 @@ public void shouldReturnBidAdjustmentMediaTypeVideoOutstreamIfImpIdNotEqualBidIm eq(givenBidAdjustments()), eq(ImpMediaType.video_outstream), eq("bidder"), - eq("seat"), eq("dealId")); } @@ -680,7 +673,6 @@ public void shouldReturnBidAdjustmentMediaTypeVideoOutStreamIfImpIdEqualBidImpId eq(givenBidAdjustments()), eq(ImpMediaType.video_outstream), eq("bidder"), - eq("seat"), eq("dealId")); } @@ -724,7 +716,7 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentMediaFactorPresent() .containsExactly(BigDecimal.valueOf(6.912), BigDecimal.valueOf(1), BigDecimal.valueOf(1)); verify(bidAdjustmentsResolver, times(3)) - .resolve(any(), any(), any(), any(), any(), any(), any()); + .resolve(any(), any(), any(), any(), any(), any()); } @Test @@ -776,7 +768,6 @@ public void shouldAdjustPriceWithPriorityForMediaTypeAdjustment() { eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), - eq("seat"), eq("dealId")); } @@ -825,7 +816,6 @@ public void shouldReturnBidsWithoutAdjustingPricesWhenAdjustmentFactorNotPresent eq(givenBidAdjustments()), eq(ImpMediaType.banner), eq("bidder"), - eq("seat"), eq("dealId")); } diff --git a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java index 82594c506b9..97ca68e939e 100644 --- a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java @@ -59,7 +59,6 @@ public void resolveShouldPickAndApplyRulesBySpecificMediaType() { givenBidAdjustments, ImpMediaType.banner, "bidderName", - "seat", "dealId"); // then @@ -83,7 +82,6 @@ public void resolveShouldPickAndApplyRulesByWildcardMediaType() { givenBidAdjustments, ImpMediaType.video_outstream, "bidderName", - "seat", "dealId"); // then @@ -92,10 +90,10 @@ public void resolveShouldPickAndApplyRulesByWildcardMediaType() { } @Test - public void resolveShouldPickAndApplyRulesBySpecificSeat() { + public void resolveShouldPickAndApplyRulesBySpecificBidder() { // given final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( - "*|seat|*", List.of(givenMultiplier("15")), + "*|bidderName|*", List.of(givenMultiplier("15")), "*|*|*", List.of(givenMultiplier("25")))); // when @@ -105,7 +103,6 @@ public void resolveShouldPickAndApplyRulesBySpecificSeat() { givenBidAdjustments, ImpMediaType.banner, "bidderName", - "seat", "dealId"); // then @@ -114,10 +111,10 @@ public void resolveShouldPickAndApplyRulesBySpecificSeat() { } @Test - public void resolveShouldPickAndApplyRulesByWildcardSeat() { + public void resolveShouldPickAndApplyRulesByWildcardBidder() { // given final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( - "*|seat|*", List.of(givenStatic("15", "EUR"), givenMultiplier("15")), + "*|bidderName|*", List.of(givenStatic("15", "EUR"), givenMultiplier("15")), "*|*|*", List.of(givenStatic("25", "UAH"), givenMultiplier("25")))); // when @@ -127,51 +124,6 @@ public void resolveShouldPickAndApplyRulesByWildcardSeat() { givenBidAdjustments, ImpMediaType.banner, "anotherBidderName", - "anotherSeat", - "dealId"); - - // then - assertThat(actual).isEqualTo(Price.of("UAH", new BigDecimal("625"))); - verifyNoInteractions(currencyService); - } - - @Test - public void resolveShouldPickAndApplyRulesByWildcardSeatOverSpecificBidder() { - // given - final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( - "*|bidderName|*", List.of(givenMultiplier("15")), - "*|*|*", List.of(givenMultiplier("25")))); - - // when - final Price actual = target.resolve( - Price.of("USD", BigDecimal.ONE), - BidRequest.builder().build(), - givenBidAdjustments, - ImpMediaType.banner, - "bidderName", - "seat", - "dealId"); - - // then - assertThat(actual).isEqualTo(Price.of("USD", new BigDecimal("25"))); - verifyNoInteractions(currencyService); - } - - @Test - public void resolveShouldPickAndApplyRulesBySpecificSeatOverSpecificBidder() { - // given - final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( - "*|bidderName|*", List.of(givenStatic("15", "EUR"), givenMultiplier("15")), - "*|seat|*", List.of(givenStatic("25", "UAH"), givenMultiplier("25")))); - - // when - final Price actual = target.resolve( - Price.of("USD", BigDecimal.ONE), - BidRequest.builder().build(), - givenBidAdjustments, - ImpMediaType.banner, - "bidderName", - "seat", "dealId"); // then @@ -179,28 +131,6 @@ public void resolveShouldPickAndApplyRulesBySpecificSeatOverSpecificBidder() { verifyNoInteractions(currencyService); } - @Test - public void resolveShouldPickAndApplyRulesBySpecificBidderWhenSeatRuleIsNotMatched() { - // given - final BidAdjustments givenBidAdjustments = BidAdjustments.of(Map.of( - "*|bidderName|*", List.of(givenStatic("15", "EUR"), givenMultiplier("15")), - "*|anotherBidder|*", List.of(givenStatic("25", "UAH"), givenMultiplier("25")))); - - // when - final Price actual = target.resolve( - Price.of("USD", BigDecimal.ONE), - BidRequest.builder().build(), - givenBidAdjustments, - ImpMediaType.banner, - "bidderName", - "seat", - "dealId"); - - // then - assertThat(actual).isEqualTo(Price.of("EUR", new BigDecimal("225"))); - verifyNoInteractions(currencyService); - } - @Test public void resolveShouldPickAndApplyRulesBySpecificDealId() { // given @@ -216,7 +146,6 @@ public void resolveShouldPickAndApplyRulesBySpecificDealId() { givenBidAdjustments, ImpMediaType.banner, "bidderName", - "seat", "dealId"); // then @@ -239,7 +168,6 @@ public void resolveShouldPickAndApplyRulesByWildcardDealId() { givenBidAdjustments, ImpMediaType.banner, "bidderName", - "seat", "anotherDealId"); // then @@ -262,7 +190,6 @@ public void resolveShouldPickAndApplyRulesByWildcardDealIdWhenDealIdIsNull() { givenBidAdjustments, ImpMediaType.banner, "bidderName", - "seat", null); // then @@ -284,7 +211,6 @@ public void resolveShouldReturnEmptyListWhenNoMatchFound() { givenBidAdjustments, ImpMediaType.banner, "bidderName", - "seat", null); // then