From 88349bdb737128b085c7773ad3ca8ca6fac3f165 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 20 Mar 2025 12:36:32 +0100 Subject: [PATCH 1/6] Multiple Bidder Codes Fix --- .../server/auction/BidResponseCreator.java | 97 ++--- .../server/auction/ExchangeService.java | 2 +- .../server/auction/aliases/BidderAliases.java | 6 +- .../auction/model/BidderResponseInfo.java | 6 +- .../BidAdjustmentsProcessor.java | 24 +- .../auction/BidResponseCreatorTest.java | 368 ++++++++++-------- .../server/auction/ExchangeServiceTest.java | 37 +- .../auction/aliases/BidderAliasesTest.java | 35 ++ .../BidAdjustmentsProcessorTest.java | 146 +++---- 9 files changed, 427 insertions(+), 294 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 33db1e5db26..13833c5b21b 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -23,7 +23,6 @@ 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; @@ -82,6 +81,7 @@ import org.prebid.server.proto.openrtb.ext.response.CacheAsset; import org.prebid.server.proto.openrtb.ext.response.Events; 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.ExtBidPrebidVideo; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponse; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponseFledge; @@ -230,19 +230,17 @@ Future createOnSkippedAuction(AuctionContext auctionContext, List create(AuctionContext auctionContext, BidRequestCacheInfo cacheInfo, - BidderAliases aliases, Map bidderToMultiBids) { return videoStoredDataResult(auctionContext) .compose(videoStoredData -> - create(videoStoredData, auctionContext, cacheInfo, aliases, bidderToMultiBids)) + create(videoStoredData, auctionContext, cacheInfo, bidderToMultiBids)) .map(bidResponse -> populateSeatNonBid(auctionContext, bidResponse)); } private Future create(VideoStoredDataResult videoStoredDataResult, AuctionContext auctionContext, BidRequestCacheInfo cacheInfo, - BidderAliases aliases, Map bidderToMultiBids) { final EventsContext eventsContext = createEventsContext(auctionContext); @@ -260,7 +258,6 @@ private Future create(VideoStoredDataResult videoStoredDataResult, toBidderResponseInfos(categoryMappingResult, cacheInfo, auctionContext), auctionContext, cacheInfo, - aliases, bidderToMultiBids, videoStoredDataResult, eventsContext)); @@ -431,6 +428,8 @@ private List toBidderResponseInfos(CategoryMappingResult cat final List bidInfos = new ArrayList<>(); final BidderSeatBid seatBid = bidderResponse.getSeatBid(); + String seat = bidder; + String adapterCode = bidder; for (final BidderBid bidderBid : seatBid.getBids()) { final BidInfo bidInfo = toBidInfo( bidderBid.getBid(), @@ -442,6 +441,13 @@ private List toBidderResponseInfos(CategoryMappingResult cat cacheInfo, account); bidInfos.add(bidInfo); + seat = bidderBid.getSeat(); + adapterCode = Optional.ofNullable(bidderBid.getBid()) + .map(Bid::getExt) + .flatMap(ext -> getExtPrebid(ext, ExtBidPrebid.class)) + .map(ExtBidPrebid::getMeta) + .map(ExtBidPrebidMeta::getAdapterCode) + .orElse(bidder); } final BidderSeatBidInfo bidderSeatBidInfo = BidderSeatBidInfo.of( @@ -452,7 +458,12 @@ private List toBidderResponseInfos(CategoryMappingResult cat seatBid.getFledgeAuctionConfigs(), seatBid.getIgi()); - result.add(BidderResponseInfo.of(bidder, bidderSeatBidInfo, bidderResponse.getResponseTime())); + result.add(BidderResponseInfo.of( + bidder, + seat, + adapterCode, + bidderSeatBidInfo, + bidderResponse.getResponseTime())); } return result; @@ -587,7 +598,6 @@ private static CategoryMappingResult addCategoryMappingErrors(CategoryMappingRes private Future cacheBidsAndCreateResponse(List bidderResponses, AuctionContext auctionContext, BidRequestCacheInfo cacheInfo, - BidderAliases aliases, Map bidderToMultiBids, VideoStoredDataResult videoStoredDataResult, EventsContext eventsContext) { @@ -598,7 +608,6 @@ private Future cacheBidsAndCreateResponse(List final ExtBidResponse extBidResponse = toExtBidResponse( bidderResponses, auctionContext, - aliases, CacheServiceResult.empty(), VideoStoredDataResult.empty(), eventsContext.getAuctionTimestamp(), @@ -642,7 +651,6 @@ private Future cacheBidsAndCreateResponse(List .map(cacheResult -> toBidResponse( bidderResponseInfos, auctionContext, - aliases, targeting, cacheInfo, cacheResult, @@ -803,7 +811,6 @@ private static String targetingCode(String base, String prefix, int i) { */ private ExtBidResponse toExtBidResponse(List bidderResponseInfos, AuctionContext auctionContext, - BidderAliases aliases, CacheServiceResult cacheResult, VideoStoredDataResult videoStoredDataResult, long auctionTimestamp, @@ -813,7 +820,7 @@ private ExtBidResponse toExtBidResponse(List bidderResponseI final DebugContext debugContext = auctionContext.getDebugContext(); final boolean debugEnabled = debugContext.isDebugEnabled(); - final PaaResult paaResult = toPaaOutput(bidderResponseInfos, auctionContext, aliases); + final PaaResult paaResult = toPaaOutput(bidderResponseInfos, auctionContext); final List igi = paaResult.igis(); final ExtBidResponseFledge fledge = paaResult.fledge(); @@ -857,12 +864,10 @@ private ExtBidResponsePrebid toExtBidResponsePrebid(long auctionTimestamp, .build(); } - private PaaResult toPaaOutput(List bidderResponseInfos, - AuctionContext auctionContext, - BidderAliases aliases) { + private PaaResult toPaaOutput(List bidderResponseInfos, AuctionContext auctionContext) { final PaaFormat paaFormat = resolvePaaFormat(auctionContext); - final List igis = extractIgis(bidderResponseInfos, auctionContext, aliases); + final List igis = extractIgis(bidderResponseInfos, auctionContext); final List extIgi = paaFormat == PaaFormat.IAB && !igis.isEmpty() ? igis : null; final List fledgeConfigs = paaFormat == PaaFormat.ORIGINAL @@ -872,7 +877,7 @@ private PaaResult toPaaOutput(List bidderResponseInfos, // TODO: Remove after transition period final List imps = auctionContext.getBidRequest().getImp(); final List deprecatedFledgeConfigs = bidderResponseInfos.stream() - .flatMap(bidderResponseInfo -> toDeprecatedFledgeConfigs(bidderResponseInfo, aliases, imps)) + .flatMap(bidderResponseInfo -> toDeprecatedFledgeConfigs(bidderResponseInfo, imps)) .toList(); final List combinedFledgeConfigs = ListUtils.union(deprecatedFledgeConfigs, fledgeConfigs); @@ -883,25 +888,29 @@ private PaaResult toPaaOutput(List bidderResponseInfos, return new PaaResult(extIgi, extBidResponseFledge); } - private List extractIgis(List bidderResponseInfos, - AuctionContext auctionContext, - BidderAliases aliases) { - + private List extractIgis(List bidderResponseInfos, AuctionContext auctionContext) { return bidderResponseInfos.stream() .flatMap(responseInfo -> responseInfo.getSeatBid().getIgi().stream() - .map(igi -> prepareExtIgi(igi, responseInfo.getBidder(), auctionContext, aliases))) + .map(igi -> prepareExtIgi( + igi, + responseInfo.getSeat(), + responseInfo.getAdapterCode(), + auctionContext))) .filter(Objects::nonNull) .toList(); } - private ExtIgi prepareExtIgi(ExtIgi igi, String bidder, AuctionContext auctionContext, BidderAliases aliases) { + private ExtIgi prepareExtIgi(ExtIgi igi, + String seat, + String adapterCode, + AuctionContext auctionContext) { if (igi == null) { return null; } final boolean shouldDropIgb = StringUtils.isEmpty(igi.getImpid()) && CollectionUtils.isNotEmpty(igi.getIgb()); if (shouldDropIgb) { - final String warning = "ExtIgi with absent impId from bidder: " + bidder; + final String warning = "ExtIgi with absent impId from bidder: " + seat; if (auctionContext.getDebugContext().isDebugEnabled()) { auctionContext.getDebugWarnings().add(warning); } @@ -909,7 +918,7 @@ private ExtIgi prepareExtIgi(ExtIgi igi, String bidder, AuctionContext auctionCo metrics.updateAlertsMetrics(MetricName.general); } - final List updatedIgs = prepareExtIgiIgs(igi.getIgs(), bidder, auctionContext, aliases); + final List updatedIgs = prepareExtIgiIgs(igi.getIgs(), seat, adapterCode, auctionContext); final List preparedIgs = updatedIgs.isEmpty() ? null : updatedIgs; final List preparedIgb = shouldDropIgb ? null : igi.getIgb(); @@ -919,9 +928,9 @@ private ExtIgi prepareExtIgi(ExtIgi igi, String bidder, AuctionContext auctionCo } private List prepareExtIgiIgs(List igiIgs, - String bidder, - AuctionContext auctionContext, - BidderAliases aliases) { + String seat, + String adapterCode, + AuctionContext auctionContext) { if (igiIgs == null) { return Collections.emptyList(); @@ -935,7 +944,7 @@ private List prepareExtIgiIgs(List igiIgs, } if (StringUtils.isEmpty(extIgiIgs.getImpId())) { - final String warning = "ExtIgiIgs with absent impId from bidder: " + bidder; + final String warning = "ExtIgiIgs with absent impId from bidder: " + seat; if (debugEnabled) { auctionContext.getDebugWarnings().add(warning); } @@ -945,7 +954,7 @@ private List prepareExtIgiIgs(List igiIgs, } if (extIgiIgs.getConfig() == null) { - final String warning = "ExtIgiIgs with absent config from bidder: " + bidder; + final String warning = "ExtIgiIgs with absent config from bidder: " + seat; if (debugEnabled) { auctionContext.getDebugWarnings().add(warning); } @@ -955,7 +964,7 @@ private List prepareExtIgiIgs(List igiIgs, } final ExtIgiIgs preparedExtIgiIgs = extIgiIgs.toBuilder() - .ext(ExtIgiIgsExt.of(bidder, bidderCatalog.resolveBaseBidder(aliases.resolveBidder(bidder)))) + .ext(ExtIgiIgsExt.of(seat, adapterCode)) .build(); preparedIgiIgs.add(preparedExtIgiIgs); @@ -982,14 +991,16 @@ private static FledgeAuctionConfig extIgiIgsToFledgeConfig(ExtIgiIgs extIgiIgs) } private Stream toDeprecatedFledgeConfigs(BidderResponseInfo bidderResponseInfo, - BidderAliases aliases, List imps) { return Optional.ofNullable(bidderResponseInfo.getSeatBid().getFledgeAuctionConfigs()) .stream() .flatMap(Collection::stream) .filter(fledgeConfig -> validateFledgeConfig(fledgeConfig, imps)) - .map(fledgeConfig -> fledgeConfigWithBidder(fledgeConfig, bidderResponseInfo.getBidder(), aliases)); + .map(fledgeConfig -> fledgeConfigWithBidder( + fledgeConfig, + bidderResponseInfo.getSeat(), + bidderResponseInfo.getAdapterCode())); } private boolean validateFledgeConfig(FledgeAuctionConfig fledgeAuctionConfig, List imps) { @@ -1002,12 +1013,12 @@ private boolean validateFledgeConfig(FledgeAuctionConfig fledgeAuctionConfig, Li } private FledgeAuctionConfig fledgeConfigWithBidder(FledgeAuctionConfig fledgeConfig, - String bidder, - BidderAliases aliases) { + String seat, + String adapterCode) { return fledgeConfig.toBuilder() - .bidder(bidder) - .adapter(bidderCatalog.resolveBaseBidder(aliases.resolveBidder(bidder))) + .bidder(seat) + .adapter(adapterCode) .build(); } @@ -1095,7 +1106,7 @@ private static Map> toExtHttpCalls(List> bidderHttpCalls = bidderResponses.stream() .filter(bidderResponse -> CollectionUtils.isNotEmpty(bidderResponse.getSeatBid().getHttpCalls())) .collect(Collectors.toMap( - BidderResponseInfo::getBidder, + BidderResponseInfo::getSeat, bidderResponse -> bidderResponse.getSeatBid().getHttpCalls())); final DebugHttpCall httpCall = cacheResult.getHttpCall(); @@ -1166,7 +1177,7 @@ private static Map> extractBidderErrors( return bidderResponses.stream() .filter(bidderResponse -> CollectionUtils.isNotEmpty(bidderResponse.getSeatBid().getErrors())) - .collect(Collectors.toMap(BidderResponseInfo::getBidder, + .collect(Collectors.toMap(BidderResponseInfo::getSeat, bidderResponse -> errorsDetails(bidderResponse.getSeatBid().getErrors()))); } @@ -1178,7 +1189,7 @@ private static Map> extractBidderWarnings( return bidderResponses.stream() .filter(bidderResponse -> CollectionUtils.isNotEmpty(bidderResponse.getSeatBid().getWarnings())) - .collect(Collectors.toMap(BidderResponseInfo::getBidder, + .collect(Collectors.toMap(BidderResponseInfo::getSeat, bidderResponse -> errorsDetails(bidderResponse.getSeatBid().getWarnings()))); } @@ -1312,7 +1323,7 @@ private static Map toResponseTimes(Collection responseTimeMillis = bidderResponses.stream() - .collect(Collectors.toMap(BidderResponseInfo::getBidder, BidderResponseInfo::getResponseTime)); + .collect(Collectors.toMap(BidderResponseInfo::getSeat, BidderResponseInfo::getResponseTime)); final DebugHttpCall debugHttpCall = cacheResult.getHttpCall(); final Integer cacheResponseTime = debugHttpCall != null ? debugHttpCall.getResponseTimeMillis() : null; @@ -1338,7 +1349,6 @@ private static PaaFormat resolvePaaFormat(AuctionContext auctionContext) { */ private BidResponse toBidResponse(List bidderResponseInfos, AuctionContext auctionContext, - BidderAliases aliases, ExtRequestTargeting targeting, BidRequestCacheInfo requestCacheInfo, CacheServiceResult cacheResult, @@ -1369,7 +1379,6 @@ private BidResponse toBidResponse(List bidderResponseInfos, final ExtBidResponse extBidResponse = toExtBidResponse( bidderResponseInfos, auctionContext, - aliases, cacheResult, videoStoredDataResult, auctionTimestamp, @@ -1480,7 +1489,7 @@ private BidInfo injectAdmWithCacheInfo(BidInfo bidInfo, final Bid bid = bidInfo.getBid(); final BidType bidType = bidInfo.getBidType(); - final String bidder = bidInfo.getBidder(); + final String seat = bidInfo.getSeat(); final Imp correspondingImp = bidInfo.getCorrespondingImp(); final CacheInfo cacheInfo = bidsWithCacheIds.get(bid); @@ -1497,7 +1506,7 @@ private BidInfo injectAdmWithCacheInfo(BidInfo bidInfo, try { modifiedBidAdm = createNativeMarkup(modifiedBidAdm, correspondingImp); } catch (PreBidException e) { - bidErrors.computeIfAbsent(bidder, ignored -> new ArrayList<>()) + bidErrors.computeIfAbsent(seat, ignored -> new ArrayList<>()) .add(ExtBidderError.of(BidderError.Type.bad_server_response.getCode(), e.getMessage())); return null; } diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index dfdf64a21a5..8d6a73a8b68 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -278,7 +278,7 @@ private Future runAuction(AuctionContext receivedContext) { .map(auctionParticipations -> updateResponsesMetrics(auctionParticipations, account, aliases)) .map(context::with)) // produce response from bidder results - .compose(context -> bidResponseCreator.create(context, cacheInfo, aliases, bidderToMultiBid) + .compose(context -> bidResponseCreator.create(context, cacheInfo, bidderToMultiBid) .map(bidResponse -> criteriaLogManager.traceResponse( logger, bidResponse, 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 6de52b67fbe..5b15859b7be 100644 --- a/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java +++ b/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java @@ -3,6 +3,7 @@ import org.apache.commons.collections4.MapUtils; 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.bidder.BidderCatalog; @@ -85,7 +86,10 @@ private Integer resolveAliasVendorIdViaCatalog(String alias) { } public boolean isAllowedAlternateBidderCode(String bidder, String alternateBidderCode) { - final Set allowedBidderCodes = bidderToAllowedBidderCodes.getOrDefault(bidder, Collections.emptySet()); + final Set allowedBidderCodes = ObjectUtils.firstNonNull( + bidderToAllowedBidderCodes.get(bidder), + bidderToAllowedBidderCodes.get(resolveBidder(bidder)), + Collections.emptySet()); return allowedBidderCodes.contains(WILDCARD) || allowedBidderCodes.contains(alternateBidderCode); } diff --git a/src/main/java/org/prebid/server/auction/model/BidderResponseInfo.java b/src/main/java/org/prebid/server/auction/model/BidderResponseInfo.java index f02a9af5b72..0de6072134d 100644 --- a/src/main/java/org/prebid/server/auction/model/BidderResponseInfo.java +++ b/src/main/java/org/prebid/server/auction/model/BidderResponseInfo.java @@ -10,11 +10,15 @@ public class BidderResponseInfo { String bidder; + String seat; + + String adapterCode; + BidderSeatBidInfo seatBid; int responseTime; public BidderResponseInfo with(BidderSeatBidInfo seatBid) { - return of(this.bidder, seatBid, this.responseTime); + return of(this.bidder, this.seat, this.adapterCode, seatBid, this.responseTime); } } diff --git a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java index e881ba5c487..f419a0ad4d4 100644 --- a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java +++ b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java @@ -1,5 +1,6 @@ package org.prebid.server.bidadjustments; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.DecimalNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; @@ -21,18 +22,22 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidAdjustmentFactors; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ImpMediaType; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import org.prebid.server.util.PbsUtil; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; public class BidAdjustmentsProcessor { private static final String ORIGINAL_BID_CPM = "origbidcpm"; private static final String ORIGINAL_BID_CURRENCY = "origbidcur"; + private static final String PREBID_EXT = "prebid"; private final CurrencyConversionService currencyService; private final BidAdjustmentFactorResolver bidAdjustmentFactorResolver; @@ -97,7 +102,7 @@ private BidderBid applyBidAdjustments(BidderBid bidderBid, final Price priceWithFactorsApplied = applyBidAdjustmentFactors( originalPrice, - bidder, + getAdapterCode(bidderBid.getBid()), bidderBid.getSeat(), bidRequest, mediaType); @@ -117,6 +122,23 @@ private BidderBid applyBidAdjustments(BidderBid bidderBid, } } + private String getAdapterCode(Bid bid) { + return Optional.ofNullable(bid.getExt()) + .filter(ext -> ext.hasNonNull(PREBID_EXT)) + .map(this::convertValue) + .map(ExtBidPrebid::getMeta) + .map(ExtBidPrebidMeta::getAdapterCode) + .orElse(null); + } + + private ExtBidPrebid convertValue(JsonNode jsonNode) { + try { + return mapper.mapper().convertValue(jsonNode.get(PREBID_EXT), ExtBidPrebid.class); + } catch (IllegalArgumentException ignored) { + return null; + } + } + private BidderBid updateBid(Price originalPrice, Price adjustedPrice, BidderBid bidderBid, BidRequest bidRequest) { final Bid bid = bidderBid.getBid(); final ObjectNode bidExt = bid.getExt(); diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index ba7fab62c86..d5534a4b326 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -33,7 +33,6 @@ 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; @@ -93,6 +92,7 @@ import org.prebid.server.proto.openrtb.ext.response.CacheAsset; import org.prebid.server.proto.openrtb.ext.response.Events; 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.ExtBidPrebidVideo; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponse; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponseFledge; @@ -203,8 +203,6 @@ public class BidResponseCreatorTest extends VertxTest { @Mock(strictness = LENIENT) private CacheDefaultTtlProperties cacheDefaultProperties; @Mock(strictness = LENIENT) - private BidderAliases aliases; - @Mock(strictness = LENIENT) private Metrics metrics; @Spy @@ -230,8 +228,6 @@ public void setUp() { given(cacheDefaultProperties.getAudioTtl()).willReturn(null); given(cacheDefaultProperties.getNativeTtl()).willReturn(null); - given(aliases.resolveBidder(any())).willAnswer(request -> request.getArgument(0)); - given(categoryMappingService.createCategoryMapping(any(), any(), any())) .willAnswer(invocationOnMock -> Future.succeededFuture( CategoryMappingResult.of(emptyMap(), emptyMap(), invocationOnMock.getArgument(0), null))); @@ -295,7 +291,7 @@ public void shouldPassBidWithGeneratedIdAndPreserveExtFieldsWhenIdGeneratorTypeU givenCacheServiceResult(singletonList(CacheInfo.empty())); // when - target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder() @@ -330,7 +326,7 @@ public void shouldSkipBidderWhenRejectedByProcessedBidderResponseHooks() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -366,7 +362,7 @@ public void shouldPassRequestModifiedByBidderRequestHooks() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -395,7 +391,7 @@ public void shouldPassOriginalTimeoutToCacheServiceIfCachingIsRequested() { givenCacheServiceResult(singletonList(CacheInfo.empty())); // when - target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + target.create(auctionContext, cacheInfo, MULTI_BIDS); // then verify(coreCacheService).cacheBidsOpenrtb(anyList(), any(), any(), any()); @@ -448,7 +444,7 @@ public void shouldRequestCacheServiceWithExpectedArguments() { givenCacheServiceResult(singletonList(CacheInfo.empty())); // when - target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -510,7 +506,7 @@ imp1, imp2, givenImp("impId3"), givenImp("impId4"))) givenCacheServiceResult(singletonList(CacheInfo.empty())); // when - target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor> bidsArgumentCaptor = ArgumentCaptor.forClass(List.class); @@ -576,7 +572,7 @@ public void shouldRequestCacheServiceWithVideoBidsToModify() { givenCacheServiceResult(singletonList(CacheInfo.empty())); // when - target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final EventsContext expectedEventContext = EventsContext.builder() @@ -637,7 +633,7 @@ public void shouldModifyBidAdmWhenBidVideoAndVastModifierReturnValue() { .willReturn(modifiedVast); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -665,7 +661,7 @@ public void shouldCallCacheServiceEvenRoundedCpmIsZero() { givenCacheServiceResult(singletonList(CacheInfo.empty())); // when - target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor> bidsArgumentCaptor = ArgumentCaptor.forClass(List.class); @@ -688,7 +684,7 @@ public void shouldSetExpectedConstantResponseFields() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, null, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, null, MULTI_BIDS).result(); // then final BidResponse responseWithExpectedFields = BidResponse.builder() @@ -715,7 +711,7 @@ public void shouldSetNbrValueTwoAndEmptySeatbidWhenIncomingBidResponsesAreEmpty( final AuctionContext auctionContext = givenAuctionContext(givenBidRequest(givenImp())); // when - final BidResponse bidResponse = target.create(auctionContext, null, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, null, MULTI_BIDS).result(); // then assertThat(bidResponse).returns(0, BidResponse::getNbr); @@ -733,7 +729,7 @@ public void shouldSetNbrValueTwoAndEmptySeatbidWhenIncomingBidResponsesDoNotCont contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, null, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, null, MULTI_BIDS).result(); // then assertThat(bidResponse).returns(0, BidResponse::getNbr); @@ -754,7 +750,7 @@ public void shouldSetNbrNullAndPopulateSeatbidWhenAtLeastOneBidIsPresent() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getNbr()).isNull(); @@ -776,7 +772,7 @@ public void shouldSkipBidderResponsesWhereSeatBidContainEmptyBids() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1); @@ -804,7 +800,7 @@ public void shouldOverrideBidIdWhenIdGeneratorIsUUID() { given(idGenerator.generateId()).willReturn("de7fc739-0a6e-41ad-8961-701c30c82166"); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -866,7 +862,7 @@ public void shouldUseGeneratedBidIdForEventAndCacheWhenIdGeneratorIsUUIDAndEvent .willReturn(events); // when - target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder() @@ -911,7 +907,7 @@ public void shouldSetExpectedResponseSeatBidAndBidFields() { givenCacheServiceResult(emptyList()); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then final ObjectNode expectedBidExt = mapper.createObjectNode(); @@ -956,11 +952,11 @@ public void shouldUpdateCacheDebugLogWithExtBidResponseWhenEnabledAndBidsReturne .auctionParticipations(toAuctionParticipant(bidderResponses))); // when - target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(auctionContext.getCachedDebugLog().buildCacheBody()) - .containsSequence("{\"responsetimemillis\":{\"bidder1\":100},\"tmaxrequest\":1000," + .containsSequence("{\"responsetimemillis\":{\"seat\":100},\"tmaxrequest\":1000," + "\"prebid\":{\"auctiontimestamp\":1000}}"); } @@ -972,7 +968,7 @@ public void shouldUpdateCacheDebugLogWithExtBidResponseWhenEnabledAndNoBidsRetur contextBuilder -> contextBuilder.cachedDebugLog(new CachedDebugLog(true, 100, null, jacksonMapper))); // when - target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(auctionContext.getCachedDebugLog().buildCacheBody()) @@ -1008,7 +1004,7 @@ public void shouldUseBidsReturnedInCategoryMapperResultAndUpdateErrors() { singletonList("Filtered bid 2")))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1034,7 +1030,7 @@ public void shouldThrowExceptionWhenCategoryMappingThrowsPrebidException() { .willReturn(Future.failedFuture(new InvalidRequestException("category exception"))); // when - final Future result = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS); + final Future result = target.create(auctionContext, CACHE_INFO, MULTI_BIDS); // then assertThat(result.failed()).isTrue(); @@ -1070,7 +1066,7 @@ public void shouldNotWriteSkadnAttributeToBidderSection() { givenCacheServiceResult(emptyList()); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then final ObjectNode expectedBidExt = mapper.createObjectNode(); @@ -1129,7 +1125,7 @@ public void shouldAddTypeToNativeBidAdm() throws JsonProcessingException { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -1190,7 +1186,7 @@ public void shouldReturnEmptyAssetIfImageTypeIsEmpty() throws JsonProcessingExce contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -1245,7 +1241,7 @@ public void shouldReturnEmptyAssetIfNoRelatedNativeAssetFound() throws JsonProce contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -1256,7 +1252,7 @@ public void shouldReturnEmptyAssetIfNoRelatedNativeAssetFound() throws JsonProce .isEmpty(); assertThat(bidResponse.getExt()) .extracting(ExtBidResponse::getErrors) - .isEqualTo(Map.of("bidder1", singletonList(ExtBidderError.of(3, + .isEqualTo(Map.of("seat", singletonList(ExtBidderError.of(3, "Response has an Image asset with ID:'123' present that doesn't exist in the request")))); } @@ -1304,7 +1300,7 @@ public void shouldReturnEmptyAssetIfIdIsNotPresentRelatedNativeAssetFound() thro contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -1315,7 +1311,7 @@ public void shouldReturnEmptyAssetIfIdIsNotPresentRelatedNativeAssetFound() thro .isEmpty(); assertThat(bidResponse.getExt()) .extracting(ExtBidResponse::getErrors) - .isEqualTo(Map.of("bidder1", singletonList(ExtBidderError.of(3, + .isEqualTo(Map.of("seat", singletonList(ExtBidderError.of(3, "Response has an Image asset with ID:'' present that doesn't exist in the request")))); } @@ -1362,7 +1358,7 @@ public void shouldReturnEmptyAssetIfDataTypeIsEmpty() throws JsonProcessingExcep contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -1397,7 +1393,7 @@ public void shouldSetBidAdmToNullIfCacheIdIsPresentAndReturnCreativeBidsIsFalse( final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder().doCaching(true).build(); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1427,7 +1423,7 @@ public void shouldSetBidAdmToNullIfVideoCacheIdIsPresentAndReturnCreativeVideoBi givenCacheServiceResult(singletonList(CacheInfo.of("id", null, null, null))); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1457,7 +1453,7 @@ public void shouldSetBidExpWhenCacheIdIsMatched() { final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder().doCaching(true).build(); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1487,7 +1483,7 @@ public void shouldSetBidExpMaxTtlWhenCacheIdIsMatchedAndBothTtlIsSet() { final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder().doCaching(true).build(); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1510,7 +1506,7 @@ public void shouldTolerateMissingExtInSeatBidAndBid() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then final ObjectNode expectedBidExt = mapper.createObjectNode(); @@ -1541,7 +1537,7 @@ public void shouldPassPreferDealsToWinningComparatorFactoryWhenBidRequestTrue() contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then verify(winningBidComparatorFactory, times(2)).create(eq(true)); @@ -1561,7 +1557,7 @@ public void shouldPassPreferDealsFalseWhenBidRequestPreferDealsIsNotDefined() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then verify(winningBidComparatorFactory, times(2)).create(eq(false)); @@ -1582,7 +1578,7 @@ public void shouldPopulateTargetingKeywords() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1618,7 +1614,7 @@ public void shouldPopulateTargetingKeywordsForAmpRequest() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1670,7 +1666,7 @@ public void shouldTruncateTargetingKeywordsByGlobalConfig() { cacheDefaultProperties); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1711,7 +1707,7 @@ public void shouldTruncateTargetingKeywordsByAccountConfig() { .auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1760,7 +1756,7 @@ public void shouldTruncateTargetingKeywordsByRequestPassedValue() { .auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -1806,7 +1802,7 @@ public void shouldReduceAndNotPopulateTargetingKeywordsForExtraBidsWhenCodePrefi contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse result = target.create(auctionContext, CACHE_INFO, aliases, multiBidMap).result(); + final BidResponse result = target.create(auctionContext, CACHE_INFO, multiBidMap).result(); // then assertThat(result.getSeatbid()) @@ -1860,7 +1856,7 @@ public void shouldNotPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIsDefine contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse result = target.create(auctionContext, CACHE_INFO, aliases, multiBidMap).result(); + final BidResponse result = target.create(auctionContext, CACHE_INFO, multiBidMap).result(); final Map expectedWinningBidTargetingMap = new HashMap<>(); expectedWinningBidTargetingMap.put("hb_pb", "4.50"); @@ -1911,7 +1907,7 @@ public void shouldReduceAndPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIs contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse result = target.create(auctionContext, CACHE_INFO, aliases, multiBidMap).result(); + final BidResponse result = target.create(auctionContext, CACHE_INFO, multiBidMap).result(); // then final Map bidder1Bid4Targeting = new HashMap<>(); @@ -1972,7 +1968,7 @@ public void shouldPopulateTargetingKeywordsForWinningBidsAndWinningBidsByBidder( contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -2023,7 +2019,7 @@ public void shouldPopulateTargetingKeywordsFromMediaTypePriceGranularities() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -2059,7 +2055,7 @@ public void shouldPopulateCacheIdHostPathAndUuidTargetingKeywords() { givenCacheServiceResult(singletonList(CacheInfo.of("cacheId", "videoId", null, null))); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -2104,7 +2100,7 @@ public void shouldPopulateTargetingKeywordsWithAdditionalValuesFromRequest() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -2137,7 +2133,7 @@ public void shouldPopulateTargetingKeywordsIfBidWasCachedAndAdmWasRemoved() { givenCacheServiceResult(singletonList(CacheInfo.of("cacheId", null, null, null))); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // Check if you didn't lost any bids because of bid change in winningBids set // then @@ -2185,7 +2181,7 @@ public void shouldAddExtPrebidEventsIfEventsAreEnabledAndExtRequestPrebidEventPr givenCacheServiceResult(emptyList()); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then final ArgumentCaptor> bidsArgumentCaptor = ArgumentCaptor.forClass(List.class); @@ -2239,7 +2235,7 @@ public void shouldAddExtPrebidEventsIfEventsAreEnabledAndAccountSupportEventsFor .willReturn(events); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -2289,7 +2285,7 @@ public void shouldAddExtPrebidEventsIfEventsAreEnabledAndDefaultAccountAnalytics .willReturn(events); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -2322,7 +2318,7 @@ public void shouldAddExtPrebidVideoToExtBidPrebidWhenVideoBids() { givenCacheServiceResult(emptyList()); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then final ArgumentCaptor> bidsArgumentCaptor = ArgumentCaptor.forClass(List.class); @@ -2357,7 +2353,7 @@ public void shouldAddDealTierSatisfiedToExtBidPrebidWhenBidsPrioritySatisfiedMin bidderResponses, emptyList()))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -2393,7 +2389,7 @@ public void shouldNotAddExtPrebidEventsIfEventsAreNotEnabled() { .auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -2427,7 +2423,7 @@ public void shouldNotAddExtPrebidEventsIfExtRequestPrebidEventsNull() { .auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -2468,7 +2464,7 @@ public void shouldNotAddExtPrebidEventsIfAccountDoesNotSupportEventsForChannel() .auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).hasSize(1) @@ -2500,7 +2496,7 @@ public void shouldReturnCacheEntityInExt() { givenCacheServiceResult(singletonList(CacheInfo.of("cacheId", "videoId", null, null))); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -2546,7 +2542,7 @@ public void shouldNotPopulateWinningBidTargetingIfIncludeWinnersFlagIsFalse() { givenCacheServiceResult(singletonList(CacheInfo.of("cacheId", "videoId", null, null))); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).flatExtracting(SeatBid::getBid) @@ -2592,7 +2588,7 @@ public void shouldNotPopulateBidderKeysTargetingIfIncludeBidderKeysFlagIsFalse() givenCacheServiceResult(singletonList(CacheInfo.of("cacheId", "videoId", null, null))); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).flatExtracting(SeatBid::getBid) @@ -2630,7 +2626,7 @@ public void shouldNotPopulateCacheIdTargetingKeywordsIfBidCpmIsZero() { givenCacheServiceResult(singletonList(CacheInfo.of("cacheId2", null, null, null))); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()).flatExtracting(SeatBid::getBid).hasSize(2) @@ -2667,7 +2663,7 @@ public void shouldNotCacheNonDealBidWithCpmIsZeroAndCacheDealBidWithZeroCpm() { givenCacheServiceResult(singletonList(CacheInfo.of("cacheId2", null, null, null))); // when - target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then final ArgumentCaptor> bidsArgumentCaptor = ArgumentCaptor.forClass(List.class); @@ -2687,7 +2683,12 @@ public void shouldPopulateBidResponseExtension() { .imp(singletonList(givenImp())) .build(); - final Bid bid = Bid.builder().id("bidId1").impid(IMP_ID).adm("[]").price(BigDecimal.valueOf(5.67)).build(); + final Bid bid = Bid.builder() + .id("bidId1") + .impid(IMP_ID) + .adm("[]") + .price(BigDecimal.valueOf(5.67)) + .build(); final List bidderResponses = singletonList(BidderResponse.of( "bidder1", BidderSeatBid.builder() @@ -2708,19 +2709,19 @@ public void shouldPopulateBidResponseExtension() { new RuntimeException("cacheError"), emptyMap())); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then final ExtBidResponse responseExt = bidResponse.getExt(); assertThat(responseExt.getDebug()).isNull(); assertThat(responseExt.getWarnings()) - .containsEntry("bidder1", singletonList(ExtBidderError.of(999, "some_warning"))); + .containsEntry("seat", singletonList(ExtBidderError.of(999, "some_warning"))); assertThat(responseExt.getUsersync()).isNull(); assertThat(responseExt.getTmaxrequest()).isEqualTo(1000L); assertThat(responseExt.getErrors()).hasSize(2).containsOnly( - entry("bidder1", asList( + entry("seat", asList( ExtBidderError.of(2, "bad_input"), ExtBidderError.of(3, "Failed to decode: Cannot deserialize value" + " of type `com.iab.openrtb.response.Response` from Array value " @@ -2729,7 +2730,7 @@ public void shouldPopulateBidResponseExtension() { entry("cache", singletonList(ExtBidderError.of(999, "cacheError")))); assertThat(responseExt.getResponsetimemillis()).hasSize(2) - .containsOnly(entry("bidder1", 100), entry("cache", 666)); + .containsOnly(entry("seat", 100), entry("cache", 666)); verify(coreCacheService).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -2770,7 +2771,7 @@ public void shouldPopulateBidExpBasedOnCachedResult() { given(mediaTypeCacheTtl.getBannerCacheTtl()).willReturn(50); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -2822,7 +2823,7 @@ public void impToStoredVideoJsonShouldTolerateWhenStoredVideoFetchIsFailed() { Future.failedFuture("Fetch failed")); // when - final Future result = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS); + final Future result = target.create(auctionContext, CACHE_INFO, MULTI_BIDS); // then verify(storedRequestProcessor).videoStoredDataResult(any(), eq(singletonList(imp)), anyList(), eq(timeout)); @@ -2879,7 +2880,7 @@ public void impToStoredVideoJsonShouldInjectStoredVideoWhenExtOptionsIsTrueAndVi givenCacheServiceResult(emptyList()); // when - final Future result = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future result = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then verify(storedRequestProcessor).videoStoredDataResult(any(), eq(asList(imp1, imp3)), anyList(), @@ -2924,7 +2925,7 @@ public void impToStoredVideoJsonShouldAddErrorsWithPrebidBidderWhenStoredVideoRe .willReturn(Future.failedFuture("Bad timeout")); // when - final Future result = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS); + final Future result = target.create(auctionContext, CACHE_INFO, MULTI_BIDS); // then verify(storedRequestProcessor).videoStoredDataResult(any(), eq(singletonList(imp1)), anyList(), eq(timeout)); @@ -2933,7 +2934,7 @@ public void impToStoredVideoJsonShouldAddErrorsWithPrebidBidderWhenStoredVideoRe ExtBidResponse.builder() .errors(singletonMap("prebid", singletonList(ExtBidderError.of(BidderError.Type.generic.getCode(), "Bad timeout")))) - .responsetimemillis(singletonMap("bidder1", 100)) + .responsetimemillis(singletonMap("seat", 100)) .tmaxrequest(1000L) .prebid(ExtBidResponsePrebid.builder().auctiontimestamp(1000L).build()) .build()); @@ -2963,7 +2964,7 @@ public void shouldProcessRequestAndAddErrorAboutDeprecatedBidder() { "invalid has been deprecated and is no longer available. Use valid instead."); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getExt()).isEqualTo( @@ -2994,7 +2995,7 @@ public void shouldProcessRequestAndAddErrorFromAuctionContext() { .auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final Future result = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS); + final Future result = target.create(auctionContext, CACHE_INFO, MULTI_BIDS); // then assertThat(result.result().getExt()).isEqualTo( @@ -3002,7 +3003,7 @@ public void shouldProcessRequestAndAddErrorFromAuctionContext() { .errors(singletonMap( "prebid", singletonList(ExtBidderError.of(BidderError.Type.generic.getCode(), "privacy error")))) - .responsetimemillis(singletonMap("bidder1", 100)) + .responsetimemillis(singletonMap("seat", 100)) .tmaxrequest(1000L) .prebid(ExtBidResponsePrebid.builder().auctiontimestamp(1000L).build()) .build()); @@ -3049,7 +3050,7 @@ public void shouldPopulateResponseDebugExtensionAndWarningsIfDebugIsEnabled() { .build())); // when - final BidResponse bidResponse = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then final ExtBidResponse responseExt = bidResponse.getExt(); @@ -3057,7 +3058,7 @@ public void shouldPopulateResponseDebugExtensionAndWarningsIfDebugIsEnabled() { assertThat(responseExt.getDebug()).isNotNull(); assertThat(responseExt.getDebug().getHttpcalls()).hasSize(3) .containsOnly( - entry("bidder1", singletonList(ExtHttpCall.builder().status(200).build())), + entry("seat", singletonList(ExtHttpCall.builder().status(200).build())), entry("cache", singletonList(ExtHttpCall.builder().uri("test.uri").status(500).build())), entry("userservice", singletonList(ExtHttpCall.builder().uri("userservice.uri").status(500) .build()))); @@ -3111,7 +3112,7 @@ public void shouldPassIntegrationToCacheServiceAndBidEvents() { "http://imp-url?param=value&int=integration")); // when - final Future result = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future result = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then verify(coreCacheService).cacheBidsOpenrtb(anyList(), any(), any(), @@ -3154,7 +3155,7 @@ public void shouldPopulateActivityInfrastructureTraceLogOnSpecifiedTraceLevel() .auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse) @@ -3188,7 +3189,7 @@ public void shouldPopulateBidResponseExtErrorIfImpExtIsInvalid() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getExt().getErrors().get("prebid").getFirst().getMessage()).isEqualTo(errorMessage); @@ -3208,7 +3209,7 @@ public void shouldThrowErrorIfBidIdAndCorrespondingImpIdNotEquals() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final Future bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS); + final Future bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS); // when assertThat(bidResponse.failed()).isTrue(); @@ -3228,8 +3229,7 @@ public void shouldThrowExceptionWhenBidAdmIsParsedButImpNativeNotFound() throws .build())) .build(); - final String bidder1 = "bidder1"; - final List bidderResponses = List.of(BidderResponse.of(bidder1, + final List bidderResponses = List.of(BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final AuctionContext auctionContext = givenAuctionContext( @@ -3237,12 +3237,12 @@ public void shouldThrowExceptionWhenBidAdmIsParsedButImpNativeNotFound() throws contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getExt()) .extracting(ExtBidResponse::getErrors) - .extracting(error -> error.get(bidder1)) + .extracting(error -> error.get("seat")) .extracting(extBidderErrors -> extBidderErrors.getFirst()) .isEqualTo(ExtBidderError.of(3, "Could not find native imp")); @@ -3261,8 +3261,7 @@ public void shouldThrowExceptionWhenNativeRequestIsInvalid() throws JsonProcessi .build())) .build(); - final String bidder1 = "bidder1"; - final List bidderResponses = List.of(BidderResponse.of(bidder1, + final List bidderResponses = List.of(BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, xNative, "seat", "USD")), 100)); final ObjectNode customObjectNode = mapper.createObjectNode(); @@ -3278,12 +3277,12 @@ public void shouldThrowExceptionWhenNativeRequestIsInvalid() throws JsonProcessi contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getExt()) .extracting(ExtBidResponse::getErrors) - .extracting(error -> error.get(bidder1)) + .extracting(error -> error.get("seat")) .extracting(extBidderErrors -> extBidderErrors.getFirst()) .isEqualTo(ExtBidderError.of(3, "No content to map due to end-of-input\n" + " at [Source: (String)\"\"; line: 1, column: 0]")); @@ -3317,7 +3316,7 @@ public void shouldPopulateBidAdmIfResponseAssetsIsNull() throws JsonProcessingEx contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse) @@ -3364,7 +3363,7 @@ public void shouldPopulateEventsContextForRequestIfEventsEnabledForRequest() { .willReturn(givenEvents); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -3393,7 +3392,7 @@ public void shouldNotPopulateBidExtTargetingWhenExtRequestTargetingPricegranular contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then final ObjectNode givenDefaultBidExt = @@ -3428,7 +3427,7 @@ public void shouldNotPopulateBidExtTargetingWhenExtRequestTargetingSettingsIsFal contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then final ObjectNode givenDefaultBidExt = @@ -3454,7 +3453,7 @@ public void shouldCopyRequestExtPrebidPassThroughToResponseExtPrebidPassThroughW contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getExt()) @@ -3485,7 +3484,7 @@ public void shouldCopyImpExtPrebidPassThroughToResponseBidExtPrebidPassThroughWh contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -3498,13 +3497,19 @@ public void shouldCopyImpExtPrebidPassThroughToResponseBidExtPrebidPassThroughWh @Test public void shouldAddExtPrebidFledgeIfAvailable() { // given - given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("i1").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); final BidRequest bidRequest = givenBidRequest(identity(), identity(), imp); final FledgeAuctionConfig fledgeAuctionConfig = givenFledgeAuctionConfig("i1"); - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("i1").build(); + final Bid bid = Bid.builder() + .id("bidId1") + .price(BigDecimal.valueOf(2.37)) + .impid("i1") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter1").build()) + .build()))) + .build(); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() @@ -3518,7 +3523,7 @@ public void shouldAddExtPrebidFledgeIfAvailable() { // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3527,7 +3532,7 @@ public void shouldAddExtPrebidFledgeIfAvailable() { .first() .usingRecursiveComparison() .isEqualTo(fledgeAuctionConfig.toBuilder() - .bidder("bidder1") + .bidder("seat") .adapter("adapter1") .build()); } @@ -3535,7 +3540,6 @@ public void shouldAddExtPrebidFledgeIfAvailable() { @Test public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsIab() { // given - given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("i1").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3545,7 +3549,14 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsIab() { .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) .build(); - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("i1").build(); + final Bid bid = Bid.builder() + .id("bidId1") + .price(BigDecimal.valueOf(2.37)) + .impid("i1") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter1").build()) + .build()))) + .build(); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() @@ -3559,7 +3570,7 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsIab() { // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3569,7 +3580,7 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsIab() { .igs(singletonList(ExtIgiIgs.builder() .impId("impId") .config(mapper.createObjectNode()) - .ext(ExtIgiIgsExt.of("bidder1", "adapter1")) + .ext(ExtIgiIgsExt.of("seat", "adapter1")) .build())) .build()); } @@ -3577,7 +3588,6 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsIab() { @Test public void shouldAddExtPrebidFledgeIfAvailableAndExtRequestPrebidPaaFormatIsOriginal() { // given - given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("impId").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3587,7 +3597,14 @@ public void shouldAddExtPrebidFledgeIfAvailableAndExtRequestPrebidPaaFormatIsOri .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) .build(); - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final Bid bid = Bid.builder() + .id("bidId1") + .price(BigDecimal.valueOf(2.37)) + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter1").build()) + .build()))) + .impid("impId") + .build(); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() @@ -3601,7 +3618,7 @@ public void shouldAddExtPrebidFledgeIfAvailableAndExtRequestPrebidPaaFormatIsOri // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3614,7 +3631,7 @@ public void shouldAddExtPrebidFledgeIfAvailableAndExtRequestPrebidPaaFormatIsOri FledgeAuctionConfig.builder() .impId("impId") .config(mapper.createObjectNode()) - .bidder("bidder1") + .bidder("seat") .adapter("adapter1") .build()); } @@ -3622,7 +3639,6 @@ public void shouldAddExtPrebidFledgeIfAvailableAndExtRequestPrebidPaaFormatIsOri @Test public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsAbsentAndAccountConfigPaaFormatSetToIab() { // given - given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("impId").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3632,7 +3648,14 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsAbsentAndAcc .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) .build(); - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final Bid bid = Bid.builder() + .id("bidId1") + .price(BigDecimal.valueOf(2.37)) + .impid("impId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter1").build()) + .build()))) + .build(); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() @@ -3650,7 +3673,7 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsAbsentAndAcc // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3660,7 +3683,7 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsAbsentAndAcc .igs(singletonList(ExtIgiIgs.builder() .impId("impId") .config(mapper.createObjectNode()) - .ext(ExtIgiIgsExt.of("bidder1", "adapter1")) + .ext(ExtIgiIgsExt.of("seat", "adapter1")) .build())) .build()); } @@ -3668,7 +3691,6 @@ public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsAbsentAndAcc @Test public void shouldAddExtPrebidFledgeIfAvailableAndRequestPaaFormatIsAbsentAndAccountConfigPaaFormatSetToOriginal() { // given - given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("impId").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3678,7 +3700,14 @@ public void shouldAddExtPrebidFledgeIfAvailableAndRequestPaaFormatIsAbsentAndAcc .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) .build(); - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final Bid bid = Bid.builder() + .id("bidId1") + .price(BigDecimal.valueOf(2.37)) + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter1").build()) + .build()))) + .impid("impId") + .build(); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() @@ -3696,7 +3725,7 @@ public void shouldAddExtPrebidFledgeIfAvailableAndRequestPaaFormatIsAbsentAndAcc // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3709,7 +3738,7 @@ public void shouldAddExtPrebidFledgeIfAvailableAndRequestPaaFormatIsAbsentAndAcc FledgeAuctionConfig.builder() .impId("impId") .config(mapper.createObjectNode()) - .bidder("bidder1") + .bidder("seat") .adapter("adapter1") .build()); } @@ -3717,7 +3746,6 @@ public void shouldAddExtPrebidFledgeIfAvailableAndRequestPaaFormatIsAbsentAndAcc @Test public void shouldDefaultToOriginalPaaFormat() { // given - given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("impId").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3727,7 +3755,14 @@ public void shouldDefaultToOriginalPaaFormat() { .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) .build(); - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final Bid bid = Bid.builder() + .id("bidId1") + .price(BigDecimal.valueOf(2.37)) + .impid("impId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter1").build()) + .build()))) + .build(); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() @@ -3741,7 +3776,7 @@ public void shouldDefaultToOriginalPaaFormat() { // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3754,7 +3789,7 @@ public void shouldDefaultToOriginalPaaFormat() { FledgeAuctionConfig.builder() .impId("impId") .config(mapper.createObjectNode()) - .bidder("bidder1") + .bidder("seat") .adapter("adapter1") .build()); } @@ -3762,7 +3797,6 @@ public void shouldDefaultToOriginalPaaFormat() { @Test public void shouldDropExtIgiIgbIfAvailableAndExtIgiImpIdIsAbsent() { // given - given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("impId").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3772,7 +3806,14 @@ public void shouldDropExtIgiIgbIfAvailableAndExtIgiImpIdIsAbsent() { .igb(singletonList(ExtIgiIgb.builder().build())) .build(); - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final Bid bid = Bid.builder() + .id("bidId1") + .price(BigDecimal.valueOf(2.37)) + .impid("impId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter1").build()) + .build()))) + .build(); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() @@ -3788,7 +3829,7 @@ public void shouldDropExtIgiIgbIfAvailableAndExtIgiImpIdIsAbsent() { // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3801,7 +3842,7 @@ public void shouldDropExtIgiIgbIfAvailableAndExtIgiImpIdIsAbsent() { ExtIgiIgs.builder() .impId("impId") .config(mapper.createObjectNode()) - .ext(ExtIgiIgsExt.of("bidder1", "adapter1")) + .ext(ExtIgiIgsExt.of("seat", "adapter1")) .build())) .build()); @@ -3812,7 +3853,7 @@ public void shouldDropExtIgiIgbIfAvailableAndExtIgiImpIdIsAbsent() { .containsExactly( ExtBidderError.of( BidderError.Type.generic.getCode(), - "ExtIgi with absent impId from bidder: bidder1")); + "ExtIgi with absent impId from bidder: seat")); verify(metrics).updateAlertsMetrics(MetricName.general); } @@ -3829,7 +3870,13 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsImpIdIsAbsent() { .igb(singletonList(ExtIgiIgb.builder().build())) .build(); - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final Bid bid = Bid.builder() + .id("bidId1") + .price(BigDecimal.valueOf(2.37)) + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter1").build()) + .build()))) + .impid("impId").build(); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() @@ -3845,7 +3892,7 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsImpIdIsAbsent() { // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3865,7 +3912,7 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsImpIdIsAbsent() { .containsExactly( ExtBidderError.of( BidderError.Type.generic.getCode(), - "ExtIgiIgs with absent impId from bidder: bidder1")); + "ExtIgiIgs with absent impId from bidder: seat")); verify(metrics).updateAlertsMetrics(MetricName.general); } @@ -3898,7 +3945,7 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsConfigIsAbsent() { // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3918,7 +3965,7 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsConfigIsAbsent() { .containsExactly( ExtBidderError.of( BidderError.Type.generic.getCode(), - "ExtIgiIgs with absent config from bidder: bidder1")); + "ExtIgiIgs with absent config from bidder: seat")); verify(metrics).updateAlertsMetrics(MetricName.general); } @@ -3949,7 +3996,7 @@ public void shouldDropExtIgiIfAvailableAndExtIgiIgsAndExtIgiIgbAreAbsent() { // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3961,7 +4008,6 @@ public void shouldDropExtIgiIfAvailableAndExtIgiIgsAndExtIgiIgbAreAbsent() { @Test public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { // given - given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("i1").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3980,7 +4026,7 @@ public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -3990,7 +4036,7 @@ public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { .usingRecursiveComparison() .isEqualTo(fledgeAuctionConfig.toBuilder() .bidder("bidder1") - .adapter("adapter1") + .adapter("bidder1") .build()); } @@ -4013,7 +4059,7 @@ public void shouldDropFledgeResponsesReferencingUnknownImps() { // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -4045,7 +4091,7 @@ public void shouldPopulateExtPrebidSeatNonBidWhenReturnAllBidStatusFlagIsTrue() // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -4080,7 +4126,7 @@ public void shouldNotPopulateExtPrebidSeatNonBidWhenReturnAllBidStatusFlagIsFals // when final BidResponse bidResponse = target - .create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS) + .create(auctionContext, CACHE_INFO, MULTI_BIDS) .result(); // then @@ -4122,7 +4168,7 @@ public void shouldPopulateBidExtWhenExtMediaTypePriceGranularityHasValidVideoExt contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -4165,7 +4211,7 @@ public void shouldPopulateBidExtWhenExtMediaTypePriceGranularityHasValidxNativeE context -> context.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -4211,7 +4257,7 @@ public void shouldThrowErrorIfExtMediaTypePriceGranularityCannotBeParsed() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final Future bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS); + final Future bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS); // then assertThat(bidResponse.failed()).isTrue(); @@ -4236,7 +4282,7 @@ public void shouldPopulateTargetingKeywordsWithDefaultPrefixAndRelatedWarning() contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); // when - final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, aliases, MULTI_BIDS).result(); + final BidResponse bidResponse = target.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); // then assertThat(bidResponse.getSeatbid()) @@ -4300,7 +4346,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromBid() { given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4369,7 +4415,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromImp() { given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4438,7 +4484,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromRequest() { given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4507,7 +4553,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromAccountBanne given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4576,7 +4622,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromAccountVideo given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4645,7 +4691,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromMediaTypeTtl given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4714,7 +4760,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetTtlFromMediaTypeTtl given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4783,7 +4829,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetDefaultTtlForBanner given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4852,7 +4898,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetDefaultTtlForVideoB given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4921,7 +4967,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetDefaultTtlForAudioB given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -4990,7 +5036,7 @@ public void createShouldSendCacheRequestWithExpectedTtlAndSetDefaultTtlForNative given(cacheDefaultProperties.getNativeTtl()).willReturn(63); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -5049,7 +5095,7 @@ public void createShouldSendCacheRequestWithTtlFromMediaTypeWhenAccountIsEmpty() given(mediaTypeCacheTtl.getBannerCacheTtl()).willReturn(50); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -5107,7 +5153,7 @@ public void createShouldSendCacheRequestWithNoTtlAndSetEmptyTtl() { given(mediaTypeCacheTtl.getBannerCacheTtl()).willReturn(null); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); @@ -5165,7 +5211,7 @@ public void createShouldSendCacheRequestWithVideoBidWithTtlMaxOfTtlAndVideoTtl() given(mediaTypeCacheTtl.getBannerCacheTtl()).willReturn(null); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then assertThat(response.succeeded()).isTrue(); @@ -5224,7 +5270,7 @@ public void createShouldSendCacheRequestWithBannerBidWithTtlMaxOfTtlAndVideoTtl( given(mediaTypeCacheTtl.getBannerCacheTtl()).willReturn(null); // when - final Future response = target.create(auctionContext, cacheInfo, aliases, MULTI_BIDS); + final Future response = target.create(auctionContext, cacheInfo, MULTI_BIDS); // then assertThat(response.succeeded()).isTrue(); diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index d1d68c785a5..60d6365ba7c 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -292,7 +292,7 @@ public class ExchangeServiceTest extends VertxTest { @SuppressWarnings("unchecked") @BeforeEach public void setUp() { - given(bidResponseCreator.create(any(), any(), any(), any())) + given(bidResponseCreator.create(any(), any(), any())) .willReturn(Future.succeededFuture(givenBidResponseWithBids(singletonList(givenBid(identity()))))); given(bidderCatalog.isValidName(anyString())).willReturn(true); @@ -1275,7 +1275,7 @@ public void shouldReturnSeparateSeatBidsForTheSameBidderIfBiddersAliasAndBidderW .auctiontimestamp(1000L) .build()))); - given(bidResponseCreator.create(any(), any(), any(), any())) + given(bidResponseCreator.create(any(), any(), any())) .willReturn(Future.succeededFuture(BidResponse.builder() .seatbid(asList( givenSeatBid(singletonList(givenBid(identity())), identity()), @@ -1356,7 +1356,7 @@ public void shouldOverrideDebugEnabledFlag() { .httpCalls(singletonList(ExtHttpCall.builder().build())) .build())); - given(bidResponseCreator.create(any(), any(), any(), any())) + given(bidResponseCreator.create(any(), any(), any())) .willReturn(Future.succeededFuture( BidResponse.builder() .ext(ExtBidResponse.builder() @@ -1371,7 +1371,7 @@ public void shouldOverrideDebugEnabledFlag() { verify(httpBidderRequester).requestBids(any(), any(), any(), any(), any(), any(), eq(true)); final ArgumentCaptor captor = ArgumentCaptor.forClass(AuctionContext.class); - verify(bidResponseCreator).create(captor.capture(), any(), any(), anyMap()); + verify(bidResponseCreator).create(captor.capture(), any(), anyMap()); assertThat(captor.getValue().getDebugContext()).isEqualTo(DebugContext.of(true, true, null)); assertThat(result.getBidResponse().getExt().getDebug()).isNotNull(); @@ -1386,7 +1386,7 @@ public void shouldAddDebugInfoIfDebugEnabledAndPublisherAndBidderAllowedDebug() given(httpBidderRequester.requestBids(any(), any(), any(), any(), any(), any(), eq(true))) .willReturn(Future.succeededFuture(bidderSeatBid)); - given(bidResponseCreator.create(any(), any(), any(), any())) + given(bidResponseCreator.create(any(), any(), any())) .willReturn(Future.succeededFuture( BidResponse.builder() .ext(ExtBidResponse.builder() @@ -1408,7 +1408,7 @@ public void shouldAddDebugInfoIfDebugEnabledAndPublisherAndBidderAllowedDebug() verify(httpBidderRequester).requestBids(any(), any(), any(), any(), any(), any(), eq(true)); final ArgumentCaptor captor = ArgumentCaptor.forClass(AuctionContext.class); - verify(bidResponseCreator).create(captor.capture(), any(), any(), anyMap()); + verify(bidResponseCreator).create(captor.capture(), any(), anyMap()); assertThat(captor.getValue().getDebugContext()) .isEqualTo(DebugContext.of(true, true, null)); @@ -1429,7 +1429,7 @@ public void shouldNotAddDebugInfoIfPublisherIsNotAllowedToDebug() { given(debugResolver.resolveDebugForBidder(any(), eq("bidder"))) .willReturn(false); - given(bidResponseCreator.create(any(), any(), any(), any())).willReturn( + given(bidResponseCreator.create(any(), any(), any())).willReturn( Future.succeededFuture(BidResponse.builder().ext(ExtBidResponse.builder().build()).build())); // when @@ -1439,7 +1439,7 @@ public void shouldNotAddDebugInfoIfPublisherIsNotAllowedToDebug() { verify(httpBidderRequester).requestBids(any(), any(), any(), any(), any(), any(), eq(false)); final ArgumentCaptor captor = ArgumentCaptor.forClass(AuctionContext.class); - verify(bidResponseCreator).create(captor.capture(), any(), any(), anyMap()); + verify(bidResponseCreator).create(captor.capture(), any(), anyMap()); assertThat(captor.getValue().getDebugContext()).isEqualTo( DebugContext.of(false, false, null)); @@ -1460,7 +1460,7 @@ public void shouldNotAddDebugInfoIfBidderDisabledDebug() { given(debugResolver.resolveDebugForBidder(any(), eq("bidder"))) .willReturn(false); - given(bidResponseCreator.create(any(), any(), any(), any())).willReturn( + given(bidResponseCreator.create(any(), any(), any())).willReturn( Future.succeededFuture(BidResponse.builder().ext(ExtBidResponse.builder().build()).build())); // when @@ -1470,7 +1470,7 @@ public void shouldNotAddDebugInfoIfBidderDisabledDebug() { verify(httpBidderRequester).requestBids(any(), any(), any(), any(), any(), any(), eq(false)); final ArgumentCaptor captor = ArgumentCaptor.forClass(AuctionContext.class); - verify(bidResponseCreator).create(captor.capture(), any(), any(), anyMap()); + verify(bidResponseCreator).create(captor.capture(), any(), anyMap()); assertThat(captor.getValue().getDebugContext()).isEqualTo( DebugContext.of(true, true, null)); @@ -1549,7 +1549,7 @@ public void shouldCallBidResponseCreatorWithExpectedParamsAndUpdateDebugErrors() final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(AuctionContext.class); verify(bidResponseCreator) - .create(contextArgumentCaptor.capture(), eq(expectedCacheInfo), any(), eq(expectedMultiBidMap)); + .create(contextArgumentCaptor.capture(), eq(expectedCacheInfo), eq(expectedMultiBidMap)); final Bid expectedThirdBid = Bid.builder() .id("bidId3") @@ -1622,7 +1622,6 @@ public void shouldCallBidResponseCreatorWithWinningOnlyTrueWhenIncludeBidderKeys verify(bidResponseCreator).create( auctionContextArgumentCaptor.capture(), eq(BidRequestCacheInfo.builder().doCaching(true).shouldCacheWinningBidsOnly(true).build()), - any(), eq(emptyMap())); assertThat(singletonList(auctionContextArgumentCaptor.getValue().getBidRequest())) @@ -1657,7 +1656,7 @@ public void shouldCallBidResponseCreatorWithWinningOnlyFalseWhenWinningOnlyIsNul target.holdAuction(givenRequestContext(bidRequest)); // then - verify(bidResponseCreator).create(any(), eq(BidRequestCacheInfo.builder().build()), any(), eq(emptyMap())); + verify(bidResponseCreator).create(any(), eq(BidRequestCacheInfo.builder().build()), eq(emptyMap())); } @Test @@ -3854,7 +3853,7 @@ public void shouldReduceBidsHavingDealIdWithSameImpIdByBidderWithToleratingNotOb // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(AuctionContext.class); - verify(bidResponseCreator).create(contextArgumentCaptor.capture(), any(), any(), any()); + verify(bidResponseCreator).create(contextArgumentCaptor.capture(), any(), any()); assertThat(contextArgumentCaptor.getValue().getAuctionParticipations()).hasSize(1) .extracting(AuctionParticipation::getBidderResponse) .extracting(BidderResponse::getSeatBid) @@ -3886,7 +3885,7 @@ public void shouldReduceBidsHavingDealIdWithSameImpIdByBidderWithToleratingNotOb // then final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(AuctionContext.class); - verify(bidResponseCreator).create(contextArgumentCaptor.capture(), any(), any(), any()); + verify(bidResponseCreator).create(contextArgumentCaptor.capture(), any(), any()); assertThat(contextArgumentCaptor.getValue().getAuctionParticipations()).hasSize(1) .extracting(AuctionParticipation::getBidderResponse) @@ -3915,7 +3914,6 @@ public void shouldResponseWithEmptySeatBidIfBidderNotSupportProvidedMediaTypes() .build(), 0))), any(), - any(), any())) .willReturn(Future.succeededFuture(BidResponse.builder().id("uniqId").build())); @@ -3968,7 +3966,6 @@ public void shouldResponseWithEmptySeatBidIfBidderNotSupportRequestCurrency() { .build(), 0))), any(), - any(), any())) .willReturn(Future.succeededFuture(BidResponse.builder().id("uniqId").build())); @@ -4190,7 +4187,7 @@ private BidRequest captureBidRequest() { private List captureAuctionParticipations() { final ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(AuctionContext.class); - verify(bidResponseCreator).create(contextArgumentCaptor.capture(), any(), any(), any()); + verify(bidResponseCreator).create(contextArgumentCaptor.capture(), any(), any()); return contextArgumentCaptor.getValue().getAuctionParticipations(); } @@ -4294,12 +4291,12 @@ private static ExtRequestTargeting givenTargeting(boolean includebidderkeys) { } private void givenBidResponseCreator(List bids) { - given(bidResponseCreator.create(any(), any(), any(), any())) + given(bidResponseCreator.create(any(), any(), any())) .willReturn(Future.succeededFuture(givenBidResponseWithBids(bids))); } private void givenBidResponseCreator(Map> errors) { - given(bidResponseCreator.create(any(), any(), any(), any())) + given(bidResponseCreator.create(any(), any(), any())) .willReturn(Future.succeededFuture(givenBidResponseWithError(errors))); } diff --git a/src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java b/src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java index 2b8fefcde5e..d0cd4b2b2ab 100644 --- a/src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java +++ b/src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java @@ -279,4 +279,39 @@ public void isAllowedAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCode // when and then assertThat(aliases.isAllowedAlternateBidderCode("bidder", "seat")).isTrue(); } + + @Test + public void isAllowedAlternateBidderCodeShouldReturnTrueForActualBidderWhenAliasIsNotDefined() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("seat")))); + + final BidderAliases aliases = BidderAliases.of( + Map.of("alias", "bidder"), + null, + bidderCatalog, + alternateBidderCodes); + + // when and then + assertThat(aliases.isAllowedAlternateBidderCode("alias", "seat")).isTrue(); + } + + @Test + public void isAllowedAlternateBidderCodeShouldReturnTrueForAliasWhenAliasIsDefined() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("another")), + "alias", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("seat")))); + + final BidderAliases aliases = BidderAliases.of( + Map.of("alias", "bidder"), + null, + bidderCatalog, + alternateBidderCodes); + + // when and then + assertThat(aliases.isAllowedAlternateBidderCode("alias", "seat")).isTrue(); + } } diff --git a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java index 15cec732ccf..2875d044cad 100644 --- a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java @@ -31,6 +31,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ImpMediaType; import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import java.math.BigDecimal; import java.util.EnumMap; @@ -200,8 +202,14 @@ public void shouldDropBidIfPrebidExceptionWasThrownDuringBidAdjustmentResolving( @Test public void shouldUpdateBidPriceWithCurrencyConversionAndPriceAdjustmentFactorAndBidAdjustments() { // given - final BidderResponse bidderResponse = givenBidderResponse( - Bid.builder().impid("impId").price(BigDecimal.valueOf(2.0)).dealid("dealId").build()); + final BidderResponse bidderResponse = givenBidderResponse(Bid.builder() + .impid("impId") + .price(BigDecimal.valueOf(2.0)) + .dealid("dealId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter").build()) + .build()))) + .build()); final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder().build(); givenAdjustments.addFactor("bidder", BigDecimal.TEN); @@ -215,7 +223,7 @@ public void shouldUpdateBidPriceWithCurrencyConversionAndPriceAdjustmentFactorAn final AuctionParticipation auctionParticipation = givenAuctionParticipation(bidderResponse, bidRequest); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder", "seat")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "adapter", "seat")) .willReturn(BigDecimal.TEN); final Price adjustedPrice = Price.of("EUR", BigDecimal.valueOf(5.0)); given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) @@ -385,11 +393,18 @@ public void shouldUpdateBidPriceWithCurrencyConversionForMultipleBid() { public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentFactorPresent() { // given final BidderResponse bidderResponse = givenBidderResponse( - Bid.builder().impid("impId").price(BigDecimal.valueOf(2)).dealid("dealId").build()); + Bid.builder() + .impid("impId") + .price(BigDecimal.valueOf(2)) + .dealid("dealId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter").build()) + .build()))) + .build()); final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder().build(); givenAdjustments.addFactor("bidder", BigDecimal.valueOf(2.468)); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder", "seat")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "adapter", "seat")) .willReturn(BigDecimal.valueOf(2.468)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), @@ -423,24 +438,23 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentFactorPresent() { @Test public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoPlacementEqualsOne() { // given - final BidderResponse bidderResponse = BidderResponse.of( - "bidder", - BidderSeatBid.builder() - .bids(List.of( - givenBidderBid(Bid.builder() - .impid("123") - .price(BigDecimal.valueOf(2)) - .dealid("dealId") - .build(), - "USD", video))) - .build(), - 1); + final BidderSeatBid seatBid = BidderSeatBid.builder().bids(List.of(givenBidderBid(Bid.builder() + .impid("123") + .price(BigDecimal.valueOf(2)) + .dealid("dealId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter").build()) + .build()))) + .build(), + "USD", video))) + .build(); + final BidderResponse bidderResponse = BidderResponse.of("bidder", seatBid, 1); final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder() .mediatypes(new EnumMap<>(singletonMap(ImpMediaType.video, singletonMap("bidder", BigDecimal.valueOf(3.456))))) .build(); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video, givenAdjustments, "bidder", "seat")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video, givenAdjustments, "adapter", "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), impBuilder -> @@ -475,24 +489,23 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP @Test public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoPlcmtEqualsOne() { // given - final BidderResponse bidderResponse = BidderResponse.of( - "bidder", - BidderSeatBid.builder() - .bids(List.of( - givenBidderBid(Bid.builder() - .impid("123") - .price(BigDecimal.valueOf(2)) - .dealid("dealId") - .build(), - "USD", video))) - .build(), - 1); + final BidderSeatBid seatBid = BidderSeatBid.builder().bids(List.of(givenBidderBid(Bid.builder() + .impid("123") + .price(BigDecimal.valueOf(2)) + .dealid("dealId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter").build()) + .build()))) + .build(), + "USD", video))) + .build(); + final BidderResponse bidderResponse = BidderResponse.of("bidder", seatBid, 1); final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder() .mediatypes(new EnumMap<>(singletonMap(ImpMediaType.video, singletonMap("bidder", BigDecimal.valueOf(3.456))))) .build(); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video, givenAdjustments, "bidder", "seat")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video, givenAdjustments, "adapter", "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), impBuilder -> @@ -527,24 +540,26 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP @Test public void shouldReturnBidsWithAdjustedPricesWithVideoOutstreamMediaTypeIfVideoPlacementAndPlcmtIsMissing() { // given + final BidderSeatBid seatBid = BidderSeatBid.builder().bids(List.of(givenBidderBid(Bid.builder() + .impid("123") + .price(BigDecimal.valueOf(2)) + .dealid("dealId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter").build()) + .build()))) + .build(), + "USD", video))) + .build(); final BidderResponse bidderResponse = BidderResponse.of( "bidder", - BidderSeatBid.builder() - .bids(List.of( - givenBidderBid(Bid.builder() - .impid("123") - .price(BigDecimal.valueOf(2)) - .dealid("dealId") - .build(), - "USD", video))) - .build(), + seatBid, 1); final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder() .mediatypes(new EnumMap<>(singletonMap(ImpMediaType.video, singletonMap("bidder", BigDecimal.valueOf(3.456))))) .build(); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video_outstream, givenAdjustments, "bidder", "seat")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.video_outstream, givenAdjustments, "adapter", "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), impBuilder -> @@ -578,18 +593,17 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoOutstreamMediaTypeIfVideo @Test public void shouldReturnBidAdjustmentMediaTypeVideoOutstreamIfImpIdNotEqualBidImpId() { // given - final BidderResponse bidderResponse = BidderResponse.of( - "bidder", - BidderSeatBid.builder() - .bids(List.of( - givenBidderBid(Bid.builder() - .impid("125") - .price(BigDecimal.valueOf(2)) - .dealid("dealId") - .build(), - "USD", video))) - .build(), - 1); + final BidderSeatBid seatBid = BidderSeatBid.builder().bids(List.of(givenBidderBid(Bid.builder() + .impid("125") + .price(BigDecimal.valueOf(2)) + .dealid("dealId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter").build()) + .build()))) + .build(), + "USD", video))) + .build(); + final BidderResponse bidderResponse = BidderResponse.of("bidder", seatBid, 1); final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder() .mediatypes(new EnumMap<>(singletonMap(ImpMediaType.video, @@ -616,7 +630,7 @@ public void shouldReturnBidAdjustmentMediaTypeVideoOutstreamIfImpIdNotEqualBidIm .extracting(Bid::getPrice) .containsExactly(BigDecimal.valueOf(2)); - verify(bidAdjustmentFactorResolver).resolve(ImpMediaType.video_outstream, givenAdjustments, "bidder", "seat"); + verify(bidAdjustmentFactorResolver).resolve(ImpMediaType.video_outstream, givenAdjustments, "adapter", "seat"); verify(bidAdjustmentsResolver).resolve( eq(Price.of("USD", BigDecimal.valueOf(2))), eq(bidRequest), @@ -693,7 +707,7 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentMediaFactorPresent() .mediatypes(new EnumMap<>(singletonMap(ImpMediaType.banner, singletonMap("bidder", BigDecimal.valueOf(3.456))))) .build(); - given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "bidder", "seat")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, null, "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), @@ -722,17 +736,19 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentMediaFactorPresent() @Test public void shouldAdjustPriceWithPriorityForMediaTypeAdjustment() { // given + final BidderSeatBid seatBid = BidderSeatBid.builder().bids(List.of(givenBidderBid(Bid.builder() + .impid("123") + .price(BigDecimal.valueOf(2)) + .dealid("dealId") + .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(ExtBidPrebid.builder() + .meta(ExtBidPrebidMeta.builder().adapterCode("adapter").build()) + .build()))) + .build(), + "USD"))) + .build(); final BidderResponse bidderResponse = BidderResponse.of( "bidder", - BidderSeatBid.builder() - .bids(List.of( - givenBidderBid(Bid.builder() - .impid("123") - .price(BigDecimal.valueOf(2)) - .dealid("dealId") - .build(), - "USD"))) - .build(), + seatBid, 1); final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder() @@ -740,7 +756,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", "seat")) + given(bidAdjustmentFactorResolver.resolve(ImpMediaType.banner, givenAdjustments, "adapter", "seat")) .willReturn(BigDecimal.valueOf(3.456)); final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), From 118f1ba8bacdf53e97a4705887c21ed4f041f9a1 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 20 Mar 2025 12:42:24 +0100 Subject: [PATCH 2/6] Multiple Bidder Codes Fix --- .../server/auction/BidResponseCreator.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 13833c5b21b..948299c9d59 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -430,6 +430,7 @@ private List toBidderResponseInfos(CategoryMappingResult cat String seat = bidder; String adapterCode = bidder; + boolean seatAndAdapterCodeSet = false; for (final BidderBid bidderBid : seatBid.getBids()) { final BidInfo bidInfo = toBidInfo( bidderBid.getBid(), @@ -441,13 +442,16 @@ private List toBidderResponseInfos(CategoryMappingResult cat cacheInfo, account); bidInfos.add(bidInfo); - seat = bidderBid.getSeat(); - adapterCode = Optional.ofNullable(bidderBid.getBid()) - .map(Bid::getExt) - .flatMap(ext -> getExtPrebid(ext, ExtBidPrebid.class)) - .map(ExtBidPrebid::getMeta) - .map(ExtBidPrebidMeta::getAdapterCode) - .orElse(bidder); + if (!seatAndAdapterCodeSet) { + seat = bidderBid.getSeat(); + adapterCode = Optional.ofNullable(bidderBid.getBid()) + .map(Bid::getExt) + .flatMap(ext -> getExtPrebid(ext, ExtBidPrebid.class)) + .map(ExtBidPrebid::getMeta) + .map(ExtBidPrebidMeta::getAdapterCode) + .orElse(bidder); + seatAndAdapterCodeSet = true; + } } final BidderSeatBidInfo bidderSeatBidInfo = BidderSeatBidInfo.of( From 285a11b3175e6a87e69264dfbc5eb22f375284a2 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 20 Mar 2025 14:05:28 +0100 Subject: [PATCH 3/6] Request Validation Changes --- .../server/auction/BidResponseCreator.java | 22 +-- .../server/auction/aliases/BidderAliases.java | 6 + .../server/validation/RequestValidator.java | 68 ++++++-- .../auction/aliases/BidderAliasesTest.java | 120 +++++++++++++ .../validation/RequestValidatorTest.java | 159 +++++++++++++++--- 5 files changed, 330 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 948299c9d59..c171809ca04 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -428,9 +428,15 @@ private List toBidderResponseInfos(CategoryMappingResult cat final List bidInfos = new ArrayList<>(); final BidderSeatBid seatBid = bidderResponse.getSeatBid(); - String seat = bidder; - String adapterCode = bidder; - boolean seatAndAdapterCodeSet = false; + final BidderBid firstBid = CollectionUtils.isEmpty(seatBid.getBids()) ? null : seatBid.getBids().getFirst(); + final String seat = firstBid == null ? bidder : firstBid.getSeat(); + final String adapterCode = firstBid == null ? bidder : Optional.ofNullable(firstBid.getBid()) + .map(Bid::getExt) + .flatMap(ext -> getExtPrebid(ext, ExtBidPrebid.class)) + .map(ExtBidPrebid::getMeta) + .map(ExtBidPrebidMeta::getAdapterCode) + .orElse(bidder); + for (final BidderBid bidderBid : seatBid.getBids()) { final BidInfo bidInfo = toBidInfo( bidderBid.getBid(), @@ -442,16 +448,6 @@ private List toBidderResponseInfos(CategoryMappingResult cat cacheInfo, account); bidInfos.add(bidInfo); - if (!seatAndAdapterCodeSet) { - seat = bidderBid.getSeat(); - adapterCode = Optional.ofNullable(bidderBid.getBid()) - .map(Bid::getExt) - .flatMap(ext -> getExtPrebid(ext, ExtBidPrebid.class)) - .map(ExtBidPrebid::getMeta) - .map(ExtBidPrebidMeta::getAdapterCode) - .orElse(bidder); - seatAndAdapterCodeSet = true; - } } final BidderSeatBidInfo bidderSeatBidInfo = BidderSeatBidInfo.of( 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 5b15859b7be..aade755a9ec 100644 --- a/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java +++ b/src/main/java/org/prebid/server/auction/aliases/BidderAliases.java @@ -93,6 +93,12 @@ public boolean isAllowedAlternateBidderCode(String bidder, String alternateBidde return allowedBidderCodes.contains(WILDCARD) || allowedBidderCodes.contains(alternateBidderCode); } + public boolean isKnownAlternateBidderCode(String alternateBidderCode) { + return bidderToAllowedBidderCodes.values().stream() + .anyMatch(knownBidderCodes -> + knownBidderCodes.contains(WILDCARD) || knownBidderCodes.contains(alternateBidderCode)); + } + private static Map> resolveAlternateBidderCodes( AlternateBidderCodesConfig alternateBidderCodes) { diff --git a/src/main/java/org/prebid/server/validation/RequestValidator.java b/src/main/java/org/prebid/server/validation/RequestValidator.java index 9e2196af27b..9a8738c9408 100644 --- a/src/main/java/org/prebid/server/validation/RequestValidator.java +++ b/src/main/java/org/prebid/server/validation/RequestValidator.java @@ -13,9 +13,10 @@ 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.aliases.AlternateBidderCodesConfig; +import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.debug.DebugContext; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.json.JacksonMapper; @@ -33,6 +34,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidAdjustmentFactors; 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.ExtRequestPrebidAlternateBidderCodesBidder; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSchain; @@ -134,11 +137,18 @@ public ValidationResult validate(Account account, if (targeting != null) { validateTargeting(targeting); } - aliases = new CaseInsensitiveMap<>(MapUtils.emptyIfNull(extRequestPrebid.getAliases())); - + aliases = ObjectUtils.defaultIfNull(extRequestPrebid.getAliases(), Collections.emptyMap()); validateAliases(aliases, warnings, account); validateAliasesGvlIds(extRequestPrebid, aliases); - validateBidAdjustmentFactors(extRequestPrebid.getBidadjustmentfactors()); + validateAlternateBidderCodes(extRequestPrebid.getAlternateBidderCodes(), aliases); + + final AlternateBidderCodesConfig alternateBidderCodesConfig = ObjectUtils.defaultIfNull( + extRequestPrebid.getAlternateBidderCodes(), + account == null ? null : account.getAlternateBidderCodes()); + + final BidderAliases bidderAliases = BidderAliases.of( + aliases, null, bidderCatalog, alternateBidderCodesConfig); + validateBidAdjustmentFactors(extRequestPrebid.getBidadjustmentfactors(), bidderAliases); validateExtBidPrebidData(extRequestPrebid.getData(), aliases, isDebugEnabled, warnings); validateSchains(extRequestPrebid.getSchains()); } @@ -219,8 +229,7 @@ private void validateCur(List currencies) throws ValidationException { private void validateAliasesGvlIds(ExtRequestPrebid extRequestPrebid, Map aliases) throws ValidationException { - final Map aliasGvlIds = new CaseInsensitiveMap<>(MapUtils.emptyIfNull( - extRequestPrebid.getAliasgvlids())); + final Map aliasGvlIds = MapUtils.emptyIfNull(extRequestPrebid.getAliasgvlids()); for (Map.Entry aliasToGvlId : aliasGvlIds.entrySet()) { @@ -241,8 +250,26 @@ private void validateAliasesGvlIds(ExtRequestPrebid extRequestPrebid, } } - private void validateBidAdjustmentFactors(ExtRequestBidAdjustmentFactors adjustmentFactors) - throws ValidationException { + private void validateAlternateBidderCodes(ExtRequestPrebidAlternateBidderCodes adjustmentFactors, + Map aliases) throws ValidationException { + + final Map alternateBidders = adjustmentFactors != null + ? adjustmentFactors.getBidders() + : Collections.emptyMap(); + + for (Map.Entry alternateBidder + : alternateBidders.entrySet()) { + + final String bidder = alternateBidder.getKey(); + if (isUnknownBidderOrAlias(bidder, aliases)) { + throw new ValidationException( + "request.ext.prebid.alternatebiddercodes.bidders.%s is not a known bidder or alias", bidder); + } + } + } + + private void validateBidAdjustmentFactors(ExtRequestBidAdjustmentFactors adjustmentFactors, + BidderAliases bidderAliases) throws ValidationException { final Map bidderAdjustments = adjustmentFactors != null ? adjustmentFactors.getAdjustments() @@ -251,6 +278,14 @@ private void validateBidAdjustmentFactors(ExtRequestBidAdjustmentFactors adjustm for (Map.Entry bidderAdjustment : bidderAdjustments.entrySet()) { final String bidder = bidderAdjustment.getKey(); + if (!bidderCatalog.isValidName(bidder) + && !bidderAliases.isAliasDefined(bidder) + && !bidderAliases.isKnownAlternateBidderCode(bidder)) { + + 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( @@ -269,17 +304,26 @@ private void validateBidAdjustmentFactors(ExtRequestBidAdjustmentFactors adjustm for (Map.Entry> entry : adjustmentsMediaTypeFactors.entrySet()) { - validateBidAdjustmentFactorsByMediatype(entry.getKey(), entry.getValue()); + validateBidAdjustmentFactorsByMediatype(entry.getKey(), entry.getValue(), bidderAliases); } } private void validateBidAdjustmentFactorsByMediatype(ImpMediaType mediaType, - Map bidderAdjustments) - throws ValidationException { + Map bidderAdjustments, + BidderAliases bidderAliases) throws ValidationException { for (Map.Entry bidderAdjustment : bidderAdjustments.entrySet()) { final String bidder = bidderAdjustment.getKey(); + if (!bidderCatalog.isValidName(bidder) + && !bidderAliases.isAliasDefined(bidder) + && !bidderAliases.isKnownAlternateBidderCode(bidder)) { + + 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( @@ -533,7 +577,7 @@ private void validateAliases(Map aliases, List warnings, } } - if (alias.equalsIgnoreCase(coreBidder)) { + if (alias.equals(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/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java b/src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java index d0cd4b2b2ab..a84149e1ef7 100644 --- a/src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java +++ b/src/test/java/org/prebid/server/auction/aliases/BidderAliasesTest.java @@ -314,4 +314,124 @@ public void isAllowedAlternateBidderCodeShouldReturnTrueForAliasWhenAliasIsDefin // when and then assertThat(aliases.isAllowedAlternateBidderCode("alias", "seat")).isTrue(); } + + @Test + public void isKnownAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreDisabledForBidder() { + // given + 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 + assertThat(aliases.isKnownAlternateBidderCode("seat")).isFalse(); + } + + @Test + public void isKnownAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreLackingSeat() { + // given + 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 + assertThat(aliases.isKnownAlternateBidderCode("seat")).isFalse(); + } + + @Test + public void isKnownAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreLackingBidders() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + null); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog, alternateBidderCodes); + + // when and then + assertThat(aliases.isKnownAlternateBidderCode("seat")).isFalse(); + } + + @Test + public void iisKnownAlternateBidderCodeShouldReturnFalseWhenAlternateBidderCodesAreDisabled() { + // given + 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 + assertThat(aliases.isKnownAlternateBidderCode("seat")).isFalse(); + } + + @Test + public void isKnownAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCodesAreNull() { + // given + 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 + assertThat(aliases.isKnownAlternateBidderCode("seat")).isTrue(); + } + + @Test + public void isKnownAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCodesContainsWildcard() { + // given + 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 + assertThat(aliases.isKnownAlternateBidderCode("seat")).isTrue(); + } + + @Test + public void isKnownAlternateBidderCodeShouldReturnTrueWhenAllowedAlternateCodesContainsSeatCaseInsensitive() { + // given + 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 + assertThat(aliases.isKnownAlternateBidderCode("seat")).isTrue(); + } + + @Test + public void isKnownAlternateBidderCodeShouldReturnTrueForActualBidderWhenAliasIsNotDefined() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("seat")))); + + final BidderAliases aliases = BidderAliases.of( + Map.of("alias", "bidder"), + null, + bidderCatalog, + alternateBidderCodes); + + // when and then + assertThat(aliases.isKnownAlternateBidderCode("seat")).isTrue(); + } + + @Test + public void isKnownAlternateBidderCodeShouldReturnTrueForAliasWhenAliasIsDefined() { + // given + final ExtRequestPrebidAlternateBidderCodes alternateBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("bidder", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("another")), + "alias", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("seat")))); + + final BidderAliases aliases = BidderAliases.of( + Map.of("alias", "bidder"), + null, + bidderCatalog, + alternateBidderCodes); + + // when and then + assertThat(aliases.isKnownAlternateBidderCode("seat")).isTrue(); + } } diff --git a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java index 709aab3e682..e4efd99feb9 100644 --- a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java @@ -34,6 +34,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidAdjustmentFactors; 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.ExtRequestPrebidAlternateBidderCodesBidder; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSchain; @@ -49,6 +51,8 @@ import java.util.Collections; import java.util.EnumMap; import java.util.List; +import java.util.Map; +import java.util.Set; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; @@ -1183,26 +1187,6 @@ 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 @@ -1346,6 +1330,118 @@ public void validateShouldReturnValidationMessageWhenAdjustmentMediaFactorNegati + "must be a positive number. Got -1.100000"); } + @Test + public void validateShouldReturnValidationMessageWhenAlternateBidderUnknown() { + // given + final ExtRequestPrebidAlternateBidderCodes unknownBidderCodes = ExtRequestPrebidAlternateBidderCodes.of( + true, + Map.of("unknownBidder", ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("*")))); + final BidRequest bidRequest = validBidRequestBuilder() + .ext(ExtRequest.of( + ExtRequestPrebid.builder() + .alternateBidderCodes(unknownBidderCodes) + .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.alternatebiddercodes.bidders.unknownBidder is not a known bidder or alias"); + } + + @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 validateShouldNotFailWhenBidderIsKnownAsAlternativeBidderCode() { + // given + final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder().build(); + givenAdjustments.addFactor("unknownBidder", BigDecimal.valueOf(1.1F)); + final ExtRequestPrebidAlternateBidderCodes givenAlternativeBidderCodes = + ExtRequestPrebidAlternateBidderCodes.of(true, Map.of("rubicon", + ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("unknownBidder")))); + final BidRequest bidRequest = validBidRequestBuilder() + .ext(ExtRequest.of( + ExtRequestPrebid.builder() + .bidadjustmentfactors(givenAdjustments) + .alternateBidderCodes(givenAlternativeBidderCodes) + .build())) + .build(); + + // when + final ValidationResult result = target.validate(Account.empty(ACCOUNT_ID), bidRequest, null, null); + + // then + assertThat(result.getErrors()).isEmpty(); + } + + @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 validateShouldNotFailWhenMediaBidderIsKnownAsAlternativeBidderCode() { + // given + final ExtRequestBidAdjustmentFactors givenAdjustments = ExtRequestBidAdjustmentFactors.builder() + .mediatypes(new EnumMap<>(Collections.singletonMap(ImpMediaType.xNative, + Collections.singletonMap("unknownBidder", BigDecimal.valueOf(1.1))))) + .build(); + givenAdjustments.addFactor("unknownBidder", BigDecimal.valueOf(1.1F)); + final ExtRequestPrebidAlternateBidderCodes givenAlternativeBidderCodes = + ExtRequestPrebidAlternateBidderCodes.of(true, Map.of("rubicon", + ExtRequestPrebidAlternateBidderCodesBidder.of(true, Set.of("unknownBidder")))); + final BidRequest bidRequest = validBidRequestBuilder() + .ext(ExtRequest.of( + ExtRequestPrebid.builder() + .bidadjustmentfactors(givenAdjustments) + .alternateBidderCodes(givenAlternativeBidderCodes) + .build())) + .build(); + + // when + final ValidationResult result = target.validate(Account.empty(ACCOUNT_ID), bidRequest, null, null); + + // then + assertThat(result.getErrors()).isEmpty(); + } + @Test public void validateShouldReturnEmptyValidationMessagesWhenBidderIsKnownAndAdjustmentIsValid() { // given @@ -1392,6 +1488,29 @@ 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 From 3ae03632c7f44306147023178743e00cf67abdbf Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 20 Mar 2025 15:39:17 +0100 Subject: [PATCH 4/6] Small fix --- .../server/validation/RequestValidator.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/prebid/server/validation/RequestValidator.java b/src/main/java/org/prebid/server/validation/RequestValidator.java index 9a8738c9408..90ba305af98 100644 --- a/src/main/java/org/prebid/server/validation/RequestValidator.java +++ b/src/main/java/org/prebid/server/validation/RequestValidator.java @@ -15,6 +15,7 @@ import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.prebid.server.auction.aliases.AlternateBidder; import org.prebid.server.auction.aliases.AlternateBidderCodesConfig; import org.prebid.server.auction.aliases.BidderAliases; import org.prebid.server.auction.model.debug.DebugContext; @@ -34,8 +35,6 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidAdjustmentFactors; 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.ExtRequestPrebidAlternateBidderCodesBidder; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSchain; @@ -250,16 +249,14 @@ private void validateAliasesGvlIds(ExtRequestPrebid extRequestPrebid, } } - private void validateAlternateBidderCodes(ExtRequestPrebidAlternateBidderCodes adjustmentFactors, + private void validateAlternateBidderCodes(AlternateBidderCodesConfig alternateBidderCodesConfig, Map aliases) throws ValidationException { - final Map alternateBidders = adjustmentFactors != null - ? adjustmentFactors.getBidders() - : Collections.emptyMap(); - - for (Map.Entry alternateBidder - : alternateBidders.entrySet()) { + final Map alternateBidders = Optional.ofNullable(alternateBidderCodesConfig) + .map(AlternateBidderCodesConfig::getBidders) + .orElse(Collections.emptyMap()); + for (Map.Entry alternateBidder : alternateBidders.entrySet()) { final String bidder = alternateBidder.getKey(); if (isUnknownBidderOrAlias(bidder, aliases)) { throw new ValidationException( From e8f72a98dd3b5d335c2244bcfb30c6e05ef7b073 Mon Sep 17 00:00:00 2001 From: Markiyan Mykush <95693607+marki1an@users.noreply.github.com> Date: Thu, 20 Mar 2025 17:37:52 +0200 Subject: [PATCH 5/6] Test:Multiple bidder codes (#3850) --- .../tests/AlternateBidderCodeSpec.groovy | 180 +++++++++++++++++- .../functional/tests/BidAdjustmentSpec.groovy | 6 + .../functional/tests/BidderParamsSpec.groovy | 27 +++ 3 files changed, 208 insertions(+), 5 deletions(-) diff --git a/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy index 048a4983050..a1ab76389aa 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy @@ -11,6 +11,7 @@ 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.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.util.PBSUtils import spock.lang.Shared @@ -78,6 +79,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == ALIAS.value assert targeting["hb_bidder_${ALIAS}"] == ALIAS.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(ALIAS.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -127,6 +131,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == AMX.value assert targeting["hb_bidder_${AMX}"] == AMX.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -172,6 +179,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == AMX.value assert targeting["hb_bidder_${AMX}"] == AMX.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -214,6 +224,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == bidderCode.value assert targeting["hb_bidder_${bidderCode}"] == bidderCode.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(bidderCode.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -270,6 +283,9 @@ class AlternateBidderCodeSpec extends BaseSpec { def logs = pbsServiceWithAmxBidder.getLogsByValue(bidRequest.accountId) assert logs.contains(INVALID_BIDDER_CODE_LOGS.formatted(bidderName, AMX, bidRequest.accountId)) + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -325,6 +341,9 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(ALIAS.value) + and: "PBS should emit validation metrics" def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(ALIAS)] @@ -376,6 +395,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == GENERIC.value assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -430,6 +452,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == bidderCode.value assert targeting["hb_bidder_${bidderCode}"] == bidderCode.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(bidderCode.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -481,6 +506,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == AMX.value assert targeting["hb_bidder_${AMX}"] == AMX.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -554,6 +582,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert !response.ext?.errors assert !response.ext?.seatnonbid + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Response shouldn't contain demand source" assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource @@ -567,16 +598,44 @@ class AlternateBidderCodeSpec extends BaseSpec { 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: true, bidders: [(AMX): new BidderConfig(enabled: false, allowedBidderCodes: [UNKNOWN])]),] + } + + def "PBS should validate and throw error 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" + pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + + then: "Request should fail with error" + def exception = thrown(PrebidServerException) + assert exception.statusCode == 400 + assert exception.responseBody == "Invalid request format: " + + "request.ext.prebid.alternatebiddercodes.bidders.unknown is not a known bidder or alias" + + + where: + requestedAlternateBidderCodes << [new AlternateBidderCodes(bidders: [(UNKNOWN): new BidderConfig()]), + new AlternateBidderCodes(enabled: true, bidders: [(UNKNOWN): new BidderConfig()]), + new AlternateBidderCodes(enabled: false, bidders: [(UNKNOWN): new BidderConfig()]), + new AlternateBidderCodes(bidders: [(UNKNOWN): new BidderConfig(enabled: false, allowedBidderCodes: [AMX])]), 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])])] } @@ -615,6 +674,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == GENERIC.value assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -666,6 +728,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == GENERIC.value assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -735,6 +800,9 @@ class AlternateBidderCodeSpec extends BaseSpec { def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) } @@ -788,6 +856,9 @@ class AlternateBidderCodeSpec extends BaseSpec { def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -837,6 +908,9 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Response shouldn't contain demand source" assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource @@ -884,6 +958,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == GENERIC.value assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -937,6 +1014,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == GENERIC.value assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -997,6 +1077,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == GENERIC.value assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Response shouldn't contain warnings and errors and seatNonBid" assert !response.ext?.warnings assert !response.ext?.errors @@ -1057,6 +1140,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == AMX.value assert targeting["hb_bidder_${AMX}"] == AMX.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1114,6 +1200,9 @@ class AlternateBidderCodeSpec extends BaseSpec { def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1166,6 +1255,9 @@ class AlternateBidderCodeSpec extends BaseSpec { def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1227,6 +1319,9 @@ class AlternateBidderCodeSpec extends BaseSpec { def metrics = pbsService.sendCollectedMetricsRequest() assert metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1274,6 +1369,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == GENERIC.value assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1331,6 +1429,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == GENERIC.value assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1351,6 +1452,72 @@ class AlternateBidderCodeSpec extends BaseSpec { null | new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) } + def "PBS shouldn't discard bid when alternate bidder code allow and soft alias with case with base bidder in alternate bidder code"() { + 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: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(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: [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) | null + null | new AlternateBidderCodes(enabled: true, bidders: [(AMX): 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", @@ -1391,6 +1558,9 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder"] == GENERIC.value assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) 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 d4fd06cad64..43b7a09777a 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy @@ -1108,6 +1108,9 @@ class BidAdjustmentSpec extends BaseSpec { assert response?.seatbid?.first?.bid?.first?.price == bidResponse.seatbid.first.bid.first.price * bidAdjustmentFactor + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + where: bidAdjustmentFactor << [0.9, 1.1] } @@ -1142,6 +1145,9 @@ class BidAdjustmentSpec extends BaseSpec { assert response?.seatbid?.first?.bid?.first?.price == bidResponse.seatbid.first.bid.first.price * bidAdjustmentFactor + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC.value) + where: bidAdjustmentFactor << [0.9, 1.1] } 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 5269d31b977..d92a6f17ee9 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy @@ -1420,6 +1420,9 @@ class BidderParamsSpec extends BaseSpec { assert targeting["hb_bidder"] == BidderName.ALIAS.value assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(ALIAS.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) } @@ -1455,6 +1458,9 @@ class BidderParamsSpec extends BaseSpec { assert targeting["hb_bidder"] == BidderName.ALIAS.value assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(ALIAS.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1505,6 +1511,9 @@ class BidderParamsSpec extends BaseSpec { assert targeting["hb_bidder"] == BidderName.ALIAS.value assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(ALIAS.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1539,6 +1548,9 @@ class BidderParamsSpec extends BaseSpec { assert targeting["hb_bidder"] == ALIAS_UPPER_CASE.value assert targeting["hb_bidder_${ALIAS_UPPER_CASE}"] == ALIAS_UPPER_CASE.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(ALIAS_UPPER_CASE.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) } @@ -1564,6 +1576,9 @@ class BidderParamsSpec extends BaseSpec { and: "Bid response should contain seat" assert response.seatbid.seat == [GENERIC_CAMEL_CASE] + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(GENERIC_CAMEL_CASE.value) + and: "Response should contain adapter code" assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [BidderName.GENERIC] } @@ -1593,6 +1608,9 @@ class BidderParamsSpec extends BaseSpec { assert targeting["hb_bidder"] == ALIAS_UPPER_CASE.value assert targeting["hb_bidder_${ALIAS_UPPER_CASE}"] == ALIAS_UPPER_CASE.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(ALIAS_UPPER_CASE.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) } @@ -1630,6 +1648,9 @@ class BidderParamsSpec extends BaseSpec { assert targeting["hb_bidder"] == BidderName.ALIAS.value assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(ALIAS.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1670,6 +1691,9 @@ class BidderParamsSpec extends BaseSpec { assert targeting["hb_bidder"] == BidderName.ALIAS.value assert targeting["hb_bidder_${BidderName.ALIAS}"] == BidderName.ALIAS.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(ALIAS.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1707,6 +1731,9 @@ class BidderParamsSpec extends BaseSpec { assert targeting["hb_bidder"] == AMX.value assert targeting["hb_bidder_${AMX}"] == AMX.value + and: "Response should contain repose millis with corresponding bidder" + assert response.ext.responsetimemillis.containsKey(AMX.value) + and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) From adfbd351df4dac118ca69271ebf4b7bac2441922 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Thu, 20 Mar 2025 17:32:30 +0100 Subject: [PATCH 6/6] Small fix --- .../org/prebid/server/validation/RequestValidator.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/prebid/server/validation/RequestValidator.java b/src/main/java/org/prebid/server/validation/RequestValidator.java index 90ba305af98..d4b9fb06726 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.aliases.AlternateBidder; @@ -136,7 +137,7 @@ 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); validateAlternateBidderCodes(extRequestPrebid.getAlternateBidderCodes(), aliases); @@ -228,7 +229,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()) { @@ -574,7 +576,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));