diff --git a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java index 5efec52a599..c161dcce193 100644 --- a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java +++ b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessor.java @@ -106,6 +106,7 @@ private BidderBid applyBidAdjustments(BidderBid bidderBid, final Price priceWithAdjustmentsApplied = applyBidAdjustmentRules( priceWithFactorsApplied, + bidderBid.getSeat(), bidder, bidRequest, mediaType, @@ -209,6 +210,7 @@ private static BigDecimal adjustPrice(BigDecimal priceAdjustmentFactor, BigDecim } private Price applyBidAdjustmentRules(Price bidPrice, + String seat, String bidder, BidRequest bidRequest, ImpMediaType mediaType, @@ -218,6 +220,7 @@ private Price applyBidAdjustmentRules(Price bidPrice, bidPrice, bidRequest, mediaType, + seat, bidder, dealId); } diff --git a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java index 45b1f83e607..46947c40e67 100644 --- a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java +++ b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsResolver.java @@ -27,11 +27,12 @@ public BidAdjustmentsResolver(CurrencyConversionService currencyService, public Price resolve(Price initialPrice, BidRequest bidRequest, ImpMediaType targetMediaType, + String targetSeat, String targetBidder, String targetDealId) { final List rules = bidAdjustmentsRulesResolver.resolve( - bidRequest, targetMediaType, targetBidder, targetDealId); + bidRequest, targetMediaType, targetSeat, targetBidder, targetDealId); return adjustPrice(initialPrice, rules, bidRequest); } diff --git a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsRulesResolver.java b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsRulesResolver.java index 748e5aab6d7..d133d997520 100644 --- a/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsRulesResolver.java +++ b/src/main/java/org/prebid/server/bidadjustments/BidAdjustmentsRulesResolver.java @@ -38,13 +38,18 @@ public BidAdjustmentsRulesResolver(JacksonMapper mapper) { this.mapper = Objects.requireNonNull(mapper).mapper(); } + public List resolve(BidRequest bidRequest, ImpMediaType targetMediaType, String targetBidder) { + return resolve(bidRequest, targetMediaType, null, targetBidder, null); + } + public List resolve(BidRequest bidRequest, ImpMediaType targetMediaType, + String targetSeat, String targetBidder, String targetDealId) { final BidAdjustmentsRules bidAdjustments = BidAdjustmentsRules.of(extractBidAdjustments(bidRequest)); - return findRules(bidAdjustments, targetMediaType, targetBidder, targetDealId); + return findRules(bidAdjustments, targetMediaType, targetSeat, targetBidder, targetDealId); } private BidAdjustments extractBidAdjustments(BidRequest bidRequest) { @@ -57,22 +62,32 @@ private BidAdjustments extractBidAdjustments(BidRequest bidRequest) { private List findRules(BidAdjustmentsRules bidAdjustments, ImpMediaType targetMediaType, + String targetSeat, String targetBidder, String targetDealId) { final Map> rules = bidAdjustments.getRules(); final PrebidConfigSource source = SimpleSource.of(WILDCARD, DELIMITER, rules.keySet()); - final PrebidConfigParameters parameters = createParameters(targetMediaType, targetBidder, targetDealId); + final PrebidConfigParameters parameters = createParameters( + targetMediaType, targetSeat, targetBidder, targetDealId); final String rule = matchingStrategy.match(source, parameters); return rule == null ? Collections.emptyList() : rules.get(rule); } - private PrebidConfigParameters createParameters(ImpMediaType mediaType, String bidder, String dealId) { + private PrebidConfigParameters createParameters(ImpMediaType mediaType, + String seat, + String bidder, + String dealId) { + final List conditionsMatchers = List.of( SimpleDirectParameter.of(mediaType.toString()), - SimpleDirectParameter.of(bidder), - StringUtils.isNotBlank(dealId) ? SimpleDirectParameter.of(dealId) : PrebidConfigParameter.wildcard()); + StringUtils.isBlank(seat) + ? SimpleDirectParameter.of(bidder) + : SimpleDirectParameter.of(List.of(seat, bidder)), + StringUtils.isBlank(dealId) + ? PrebidConfigParameter.wildcard() + : SimpleDirectParameter.of(dealId)); return SimpleParameters.of(conditionsMatchers); } diff --git a/src/main/java/org/prebid/server/bidadjustments/FloorAdjustmentsResolver.java b/src/main/java/org/prebid/server/bidadjustments/FloorAdjustmentsResolver.java index 79d1c4eea63..cb4485bfa35 100644 --- a/src/main/java/org/prebid/server/bidadjustments/FloorAdjustmentsResolver.java +++ b/src/main/java/org/prebid/server/bidadjustments/FloorAdjustmentsResolver.java @@ -56,8 +56,7 @@ public Price resolve(Price initialBidFloorPrice, String targetBidder) { final List rules = bidAdjustmentsRulesResolver.resolve( - bidRequest, targetMediaType, targetBidder, null); - + bidRequest, targetMediaType, targetBidder); return reversePrice(initialBidFloorPrice, rules, bidRequest); } diff --git a/src/main/java/org/prebid/server/bidadjustments/model/BidAdjustmentsRules.java b/src/main/java/org/prebid/server/bidadjustments/model/BidAdjustmentsRules.java index 1192a66ae9c..6d64ca1330e 100644 --- a/src/main/java/org/prebid/server/bidadjustments/model/BidAdjustmentsRules.java +++ b/src/main/java/org/prebid/server/bidadjustments/model/BidAdjustmentsRules.java @@ -2,11 +2,11 @@ import lombok.Value; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.prebid.server.bidadjustments.BidAdjustmentRulesValidator; import org.prebid.server.bidadjustments.BidAdjustmentsRulesResolver; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -23,7 +23,7 @@ public static BidAdjustmentsRules of(BidAdjustments bidAdjustments) { return BidAdjustmentsRules.of(Collections.emptyMap()); } - final Map> rules = new HashMap<>(); + final Map> rules = new CaseInsensitiveMap<>(); final Map>>> mediatypes = bidAdjustments.getRules(); diff --git a/src/main/java/org/prebid/server/util/dsl/config/impl/MostAccurateCombinationStrategy.java b/src/main/java/org/prebid/server/util/dsl/config/impl/MostAccurateCombinationStrategy.java index ea8a841df95..9cbcae877da 100644 --- a/src/main/java/org/prebid/server/util/dsl/config/impl/MostAccurateCombinationStrategy.java +++ b/src/main/java/org/prebid/server/util/dsl/config/impl/MostAccurateCombinationStrategy.java @@ -14,10 +14,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.TreeSet; /** * Priority order for four column rule sets: @@ -174,7 +174,7 @@ private static List generateWildcardsIndices(Iterable toSet(Iterable iterable) { - return iterable instanceof Set set ? set : fill(new HashSet<>(), iterable); + return fill(new TreeSet<>(String.CASE_INSENSITIVE_ORDER), iterable); } private static > C fill(C destination, Iterable source) { diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/BidAdjustmentRule.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/BidAdjustmentRule.groovy index cdffc92e7e5..92af741601f 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/BidAdjustmentRule.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/BidAdjustmentRule.groovy @@ -1,11 +1,8 @@ package org.prebid.server.functional.model.request.auction import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.databind.PropertyNamingStrategies -import com.fasterxml.jackson.databind.annotation.JsonNaming import groovy.transform.ToString -@JsonNaming(PropertyNamingStrategies.LowerCaseStrategy) @ToString(includeNames = true, ignoreNulls = true) class BidAdjustmentRule { @@ -14,4 +11,9 @@ class BidAdjustmentRule { Map> generic Map> openx Map> alias + @JsonProperty("ALIAS") + Map> aliasUpperCase + @JsonProperty("AlIaS") + Map> aliasCamelCase + Map> amx } 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 4a32f637e6f..7da1c89fffb 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy @@ -30,6 +30,7 @@ import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST import static org.prebid.server.functional.model.Currency.EUR import static org.prebid.server.functional.model.Currency.GBP import static org.prebid.server.functional.model.Currency.USD +import static org.prebid.server.functional.model.bidder.BidderName.ACUITYADS import static org.prebid.server.functional.model.bidder.BidderName.ALIAS import static org.prebid.server.functional.model.bidder.BidderName.AMX import static org.prebid.server.functional.model.bidder.BidderName.APPNEXUS @@ -73,6 +74,7 @@ class BidAdjustmentSpec extends BaseSpec { pbsService = pbsServiceFactory.getService(PbsConfig.currencyConverterConfig + AMX_CONFIG) } + @Override def cleanupSpec() { pbsServiceFactory.removeContainer(PbsConfig.currencyConverterConfig + AMX_CONFIG) } @@ -1234,7 +1236,7 @@ class BidAdjustmentSpec extends BaseSpec { where: adjustmentType << [CPM, STATIC] } - + def "PBS should adjust bid price for matching bidder and alternate bidder code when request has per-bidder bid adjustment factors"() { given: "Default bid request with bid adjustment and amx bidder" def bidRequest = BidRequest.getDefaultBidRequest(SITE).tap { @@ -1345,6 +1347,325 @@ class BidAdjustmentSpec extends BaseSpec { bidAdjustmentFactor << [0.9, 1.1] } + def "PBS shouldn't adjust bid price when bid adjustment rule doesn't match with bidder code"() { + given: "Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode" + def exactRulePrice = PBSUtils.randomPrice + def currency = USD + def adjustmentRule = new AdjustmentRule(adjustmentType: STATIC, value: exactRulePrice, currency: currency) + def bidAdjustmentRule = new BidAdjustmentRule((bidAdjustmentRuleBidder): [(WILDCARD): [adjustmentRule]]) + def bidRequest = BidRequest.defaultBidRequest.tap { + cur = [currency] + imp[0].ext.prebid.bidder.generic = null + imp[0].ext.prebid.bidder.amx = new Amx() + ext.prebid.tap { + bidAdjustments = new BidAdjustment(mediaType: [(BANNER): bidAdjustmentRule]) + alternateBidderCodes = new AlternateBidderCodes().tap { + enabled = true + bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [AMX])] + } + } + } + + and: "Default bid response with price and bidder code" + def originalPrice = PBSUtils.randomPrice + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + cur = currency + seatbid.first.bid.first.price = originalPrice + seatbid.first.bid.first.ext = new BidExt(bidderCode: ACUITYADS) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Final bid price should be adjusted according to exact rule" + assert response.seatbid.first.bid.first.price == originalPrice + assert response.cur == bidResponse.cur + + and: "Original bid price and currency should be presented in bid.ext" + verifyAll(response.seatbid.first.bid.first.ext) { + origbidcpm == originalPrice + origbidcur == bidResponse.cur + } + + and: "Bidder request should contain currency from request" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.cur == [currency] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == ACUITYADS + + where: + bidAdjustmentRuleBidder << ["alias", "aliasUpperCase", "aliasCamelCase"] + } + + def "PBS should adjust bid price when two bid adjustment rules are compatible"() { + given: "Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode" + def exactRulePrice = PBSUtils.randomPrice + def currency = USD + def dealId = PBSUtils.randomString + def adjustmentRule = new AdjustmentRule(adjustmentType: STATIC, value: exactRulePrice, currency: currency) + def firstBidAdjustmentRule = new BidAdjustmentRule(amx: [(dealId): [adjustmentRule]]) + def secondBidAdjustmentRule = new BidAdjustmentRule(amx: [(WILDCARD): [adjustmentRule]]) + def bidRequest = BidRequest.defaultBidRequest.tap { + cur = [currency] + imp[0].ext.prebid.bidder.generic = null + imp[0].ext.prebid.bidder.amx = new Amx() + ext.prebid.tap { + bidAdjustments = new BidAdjustment(mediaType: [(BANNER): firstBidAdjustmentRule, + (ANY) : secondBidAdjustmentRule]) + alternateBidderCodes = new AlternateBidderCodes().tap { + enabled = true + bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [AMX])] + } + } + } + + and: "Default bid response with price and bidder code and dealId" + def originalPrice = PBSUtils.randomPrice + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + cur = currency + seatbid.first.bid.first.price = originalPrice + seatbid.first.bid.first.ext = new BidExt(bidderCode: AMX) + seatbid.first.bid.first.dealid = dealId + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Final bid price should be adjusted according to exact rule" + assert response.seatbid.first.bid.first.price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC) + assert response.cur == bidResponse.cur + + and: "Original bid price and currency should be presented in bid.ext" + verifyAll(response.seatbid.first.bid.first.ext) { + origbidcpm == originalPrice + origbidcur == bidResponse.cur + } + + and: "Bidder request should contain currency from request" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.cur == [currency] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == AMX + } + + def "PBS should adjust bid price when bid adjustment bidder and bidder code different"() { + given: "Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode" + def exactRulePrice = PBSUtils.randomPrice + def currency = USD + def adjustmentRule = new AdjustmentRule(adjustmentType: STATIC, value: exactRulePrice, currency: currency) + def bidAdjustmentRule = new BidAdjustmentRule((bidAdjustmentRuleBidder): [(WILDCARD): [adjustmentRule]]) + def bidRequest = BidRequest.defaultBidRequest.tap { + cur = [currency] + imp[0].ext.prebid.bidder.generic = null + imp[0].ext.prebid.bidder.amx = new Amx() + ext.prebid.tap { + bidAdjustments = new BidAdjustment(mediaType: [(BANNER): bidAdjustmentRule]) + alternateBidderCodes = new AlternateBidderCodes().tap { + enabled = true + bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [AMX])] + } + } + } + + and: "Default bid response with price and bidder code" + def originalPrice = PBSUtils.randomPrice + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + cur = currency + seatbid.first.bid.first.price = originalPrice + seatbid.first.bid.first.ext = new BidExt(bidderCode: ALIAS) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Final bid price should be adjusted according to exact rule" + assert response.seatbid.first.bid.first.price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC) + assert response.cur == bidResponse.cur + + and: "Original bid price and currency should be presented in bid.ext" + verifyAll(response.seatbid.first.bid.first.ext) { + origbidcpm == originalPrice + origbidcur == bidResponse.cur + } + + and: "Bidder request should contain currency from request" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.cur == [currency] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == ALIAS + + where: + bidAdjustmentRuleBidder << ["alias", "aliasUpperCase", "aliasCamelCase"] + } + + def "PBS should adjust bid price when bid adjustment bidder and bidder code same as requested"() { + given: "Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode" + def exactRulePrice = PBSUtils.randomPrice + def currency = USD + def exactRule = new BidAdjustmentRule(amx: [(WILDCARD): [new AdjustmentRule(adjustmentType: STATIC, value: exactRulePrice, currency: currency)]]) + def bidRequest = BidRequest.defaultBidRequest.tap { + cur = [currency] + imp[0].ext.prebid.bidder.generic = null + imp[0].ext.prebid.bidder.amx = new Amx() + ext.prebid.tap { + bidAdjustments = new BidAdjustment(mediaType: [(BANNER): exactRule]) + alternateBidderCodes = new AlternateBidderCodes().tap { + enabled = true + bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [AMX])] + } + } + } + + and: "Default bid response with price and bidder code" + def originalPrice = PBSUtils.randomPrice + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + cur = currency + seatbid.first.bid.first.price = originalPrice + seatbid.first.bid.first.ext = new BidExt(bidderCode: AMX) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Final bid price should be adjusted according to exact rule" + assert response.seatbid.first.bid.first.price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC) + assert response.cur == bidResponse.cur + + and: "Original bid price and currency should be presented in bid.ext" + verifyAll(response.seatbid.first.bid.first.ext) { + origbidcpm == originalPrice + origbidcur == bidResponse.cur + } + + and: "Bidder request should contain currency from request" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.cur == [currency] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == AMX + } + + def "PBS should adjust bid price when bid adjustment bidder is the same as bidder code"() { + given: "Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode" + def exactRulePrice = PBSUtils.randomPrice + def currency = USD + def exactRule = new BidAdjustmentRule(alias: [(WILDCARD): [new AdjustmentRule(adjustmentType: STATIC, value: exactRulePrice, currency: currency)]]) + def bidRequest = BidRequest.defaultBidRequest.tap { + cur = [currency] + imp[0].ext.prebid.bidder.generic = null + imp[0].ext.prebid.bidder.amx = new Amx() + ext.prebid.tap { + bidAdjustments = new BidAdjustment(mediaType: [(BANNER): exactRule]) + alternateBidderCodes = new AlternateBidderCodes().tap { + enabled = true + bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [AMX])] + } + } + } + + and: "Default bid response with price and bidder code" + def originalPrice = PBSUtils.randomPrice + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + cur = currency + seatbid.first.bid.first.price = originalPrice + seatbid.first.bid.first.ext = new BidExt(bidderCode: ALIAS) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Final bid price should be adjusted according to exact rule" + assert response.seatbid.first.bid.first.price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC) + assert response.cur == bidResponse.cur + + and: "Original bid price and currency should be presented in bid.ext" + verifyAll(response.seatbid.first.bid.first.ext) { + origbidcpm == originalPrice + origbidcur == bidResponse.cur + } + + and: "Bidder request should contain currency from request" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.cur == [currency] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == ALIAS + } + + def "PBS should adjust bid price when bid adjustment wildcard bidder and bidder code specified"() { + given: "Bid request with ext.prebid.bidAdjustments and ext.prebid.alternateBidderCode" + def exactRulePrice = PBSUtils.randomPrice + def currency = USD + def exactRule = new BidAdjustmentRule(wildcardBidder: [(WILDCARD): [new AdjustmentRule(adjustmentType: STATIC, value: exactRulePrice, currency: currency)]]) + def bidRequest = BidRequest.defaultBidRequest.tap { + cur = [currency] + imp[0].ext.prebid.bidder.generic = null + imp[0].ext.prebid.bidder.amx = new Amx() + ext.prebid.tap { + bidAdjustments = new BidAdjustment(mediaType: [(BANNER): exactRule]) + alternateBidderCodes = new AlternateBidderCodes().tap { + enabled = true + bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [AMX])] + } + } + } + + and: "Default bid response with price and bidder code" + def originalPrice = PBSUtils.randomPrice + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { + cur = currency + seatbid.first.bid.first.price = originalPrice + seatbid.first.bid.first.ext = new BidExt(bidderCode: ALIAS) + } + bidder.setResponse(bidRequest.id, bidResponse) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest) + + then: "Final bid price should be adjusted according to exact rule" + assert response.seatbid.first.bid.first.price == getAdjustedPrice(originalPrice, exactRulePrice, STATIC) + assert response.cur == bidResponse.cur + + and: "Original bid price and currency should be presented in bid.ext" + verifyAll(response.seatbid.first.bid.first.ext) { + origbidcpm == originalPrice + origbidcur == bidResponse.cur + } + + and: "Bidder request should contain currency from request" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.cur == [currency] + + and: "Response should contain adapter code" + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] + + and: "Response should contain seatbid.seat" + assert response.seatbid[0].seat == ALIAS + } + private static BigDecimal getAdjustedPrice(BigDecimal originalPrice, BigDecimal adjustedValue, AdjustmentType adjustmentType) { diff --git a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java index 1a1f33eb5f2..375ece90181 100644 --- a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsProcessorTest.java @@ -76,7 +76,7 @@ public class BidAdjustmentsProcessorTest extends VertxTest { public void before() { given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); target = new BidAdjustmentsProcessor( @@ -100,7 +100,7 @@ public void shouldReturnBidsWithUpdatedPriceCurrencyConversionAndAdjusted() { final AuctionParticipation auctionParticipation = givenAuctionParticipation(bidderResponse, bidRequest); final Price adjustedPrice = Price.of("EUR", BigDecimal.valueOf(5.0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willReturn(adjustedPrice); final BigDecimal expectedPrice = new BigDecimal("123.5"); @@ -118,6 +118,7 @@ public void shouldReturnBidsWithUpdatedPriceCurrencyConversionAndAdjusted() { eq(Price.of("USD", BigDecimal.valueOf(2.0))), eq(bidRequest), eq(ImpMediaType.banner), + eq("seat"), eq("bidder"), eq("dealId")); } @@ -137,7 +138,7 @@ public void shouldReturnSameBidPriceIfNoChangesAppliedToBidPrice() { given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocation -> invocation.getArgument(0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); // when @@ -191,7 +192,7 @@ public void shouldDropBidIfPrebidExceptionWasThrownDuringBidAdjustmentResolving( given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocation -> invocation.getArgument(0)); - given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willThrow(new PreBidException("Unable to convert bid currency CUR to desired ad server currency USD")); // when @@ -233,7 +234,7 @@ public void shouldUpdateBidPriceWithCurrencyConversionAndPriceAdjustmentFactorAn 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())) + given(bidAdjustmentsResolver.resolve(any(), any(), any(), any(), any(), any())) .willReturn(adjustedPrice); final BigDecimal expectedPrice = new BigDecimal("123.5"); given(currencyService.convertCurrency(any(), any(), eq("EUR"), eq("UAH"))).willReturn(expectedPrice); @@ -252,6 +253,7 @@ public void shouldUpdateBidPriceWithCurrencyConversionAndPriceAdjustmentFactorAn eq(Price.of("USD", BigDecimal.valueOf(20.0))), eq(bidRequest), eq(ImpMediaType.banner), + eq("seat"), eq("bidder"), eq("dealId")); } @@ -395,7 +397,7 @@ public void shouldUpdateBidPriceWithCurrencyConversionForMultipleBid() { .extracting(Bid::getPrice) .containsOnly(bidder3Price, updatedPrice, updatedPrice); - verify(bidAdjustmentsResolver, times(3)).resolve(any(), any(), any(), any(), any()); + verify(bidAdjustmentsResolver, times(3)).resolve(any(), any(), any(), any(), any(), any()); } @Test @@ -439,6 +441,7 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentFactorPresent() { eq(Price.of("USD", BigDecimal.valueOf(4.936))), eq(bidRequest), eq(ImpMediaType.banner), + eq("seat"), eq("bidder"), eq("dealId")); } @@ -489,6 +492,7 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP eq(Price.of("USD", BigDecimal.valueOf(6.912))), eq(bidRequest), eq(ImpMediaType.video_instream), + eq("seat"), eq("bidder"), eq("dealId")); } @@ -539,6 +543,7 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoP eq(Price.of("USD", BigDecimal.valueOf(6.912))), eq(bidRequest), eq(ImpMediaType.video_instream), + eq("seat"), eq("bidder"), eq("dealId")); } @@ -591,6 +596,7 @@ public void shouldReturnBidsWithAdjustedPricesWithVideoOutstreamMediaTypeIfVideo eq(Price.of("USD", BigDecimal.valueOf(6.912))), eq(bidRequest), eq(ImpMediaType.video_outstream), + eq("seat"), eq("bidder"), eq("dealId")); } @@ -640,6 +646,7 @@ public void shouldReturnBidAdjustmentMediaTypeVideoOutstreamIfImpIdNotEqualBidIm eq(Price.of("USD", BigDecimal.valueOf(2))), eq(bidRequest), eq(ImpMediaType.video_outstream), + eq("seat"), eq("bidder"), eq("dealId")); } @@ -689,6 +696,7 @@ public void shouldReturnBidAdjustmentMediaTypeVideoOutStreamIfImpIdEqualBidImpId eq(Price.of("USD", BigDecimal.valueOf(2))), eq(bidRequest), eq(ImpMediaType.video_outstream), + eq("seat"), eq("bidder"), eq("dealId")); } @@ -732,7 +740,7 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentMediaFactorPresent() .extracting(Bid::getPrice) .containsExactly(BigDecimal.valueOf(6.912), BigDecimal.valueOf(1), BigDecimal.valueOf(1)); - verify(bidAdjustmentsResolver, times(3)).resolve(any(), any(), any(), any(), any()); + verify(bidAdjustmentsResolver, times(3)).resolve(any(), any(), any(), any(), any(), any()); } @Test @@ -784,6 +792,7 @@ public void shouldAdjustPriceWithPriorityForMediaTypeAdjustment() { eq(Price.of("USD", BigDecimal.valueOf(6.912))), eq(bidRequest), eq(ImpMediaType.banner), + eq("seat"), eq("bidder"), eq("dealId")); } @@ -831,6 +840,7 @@ public void shouldReturnBidsWithoutAdjustingPricesWhenAdjustmentFactorNotPresent eq(Price.of("USD", BigDecimal.ONE)), eq(bidRequest), eq(ImpMediaType.banner), + eq("seat"), eq("bidder"), eq("dealId")); } diff --git a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java index 8c81aa4adb7..3bc13250fe4 100644 --- a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsResolverTest.java @@ -52,7 +52,7 @@ public void before() { public void resolveShouldApplyStaticRule() { // given final BidRequest givenBidRequest = BidRequest.builder().build(); - given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "bidderName", "dealId")) + given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "seat", "bidderName", "dealId")) .willReturn(List.of(givenStatic("15", "EUR"))); // when @@ -60,6 +60,7 @@ public void resolveShouldApplyStaticRule() { Price.of("USD", BigDecimal.ONE), givenBidRequest, banner, + "seat", "bidderName", "dealId"); @@ -72,7 +73,7 @@ public void resolveShouldApplyStaticRule() { public void resolveShouldApplyCpmRule() { // given final BidRequest givenBidRequest = BidRequest.builder().build(); - given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, video_outstream, "bidderName", "dealId")) + given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, video_outstream, "seat", "bidderName", "dealId")) .willReturn(List.of(givenCpm("25", "UAH"))); // when @@ -80,6 +81,7 @@ public void resolveShouldApplyCpmRule() { Price.of("USD", BigDecimal.ONE), givenBidRequest, video_outstream, + "seat", "bidderName", "dealId"); @@ -92,7 +94,7 @@ public void resolveShouldApplyCpmRule() { public void resolveShouldApplyMultiplierRule() { // given final BidRequest givenBidRequest = BidRequest.builder().build(); - given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "bidderName", "dealId")) + given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "seat", "bidderName", "dealId")) .willReturn(List.of(givenMultiplier("15"))); // when @@ -100,6 +102,7 @@ public void resolveShouldApplyMultiplierRule() { Price.of("USD", BigDecimal.ONE), BidRequest.builder().build(), banner, + "seat", "bidderName", "dealId"); @@ -112,7 +115,7 @@ public void resolveShouldApplyMultiplierRule() { public void resolveShouldApplyStaticAndCpmRules() { // given final BidRequest givenBidRequest = BidRequest.builder().build(); - given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "bidderName", "dealId")) + given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "seat", "bidderName", "dealId")) .willReturn(List.of(givenStatic("25", "UAH"), givenMultiplier("25"))); // when @@ -120,6 +123,7 @@ public void resolveShouldApplyStaticAndCpmRules() { Price.of("USD", BigDecimal.ONE), BidRequest.builder().build(), banner, + "seat", "bidderName", "dealId"); @@ -132,7 +136,7 @@ public void resolveShouldApplyStaticAndCpmRules() { public void resolveShouldApplyCpmAndStaticRules() { // given final BidRequest givenBidRequest = BidRequest.builder().build(); - given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "bidderName", "dealId")) + given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "seat", "bidderName", "dealId")) .willReturn(List.of(givenCpm("15", "JPY"), givenStatic("15", "EUR"))); // when @@ -140,6 +144,7 @@ public void resolveShouldApplyCpmAndStaticRules() { Price.of("USD", BigDecimal.ONE), givenBidRequest, banner, + "seat", "bidderName", "dealId"); @@ -152,7 +157,7 @@ public void resolveShouldApplyCpmAndStaticRules() { public void resolveShouldApplyMultiplierAdnCpmRules() { // given final BidRequest givenBidRequest = BidRequest.builder().build(); - given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "bidderName", "dealId")) + given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "seat", "bidderName", "dealId")) .willReturn(List.of(givenMultiplier("25"), givenCpm("25", "UAH"))); // when @@ -160,6 +165,7 @@ public void resolveShouldApplyMultiplierAdnCpmRules() { Price.of("USD", BigDecimal.ONE), givenBidRequest, banner, + "seat", "bidderName", "dealId"); @@ -172,7 +178,7 @@ public void resolveShouldApplyMultiplierAdnCpmRules() { public void resolveShouldApplyTwoCpmRules() { // given final BidRequest givenBidRequest = BidRequest.builder().build(); - given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "bidderName", null)) + given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "seat", "bidderName", null)) .willReturn(List.of(givenCpm("25", "UAH"), givenCpm("25", "JPY"))); // when @@ -180,6 +186,7 @@ public void resolveShouldApplyTwoCpmRules() { Price.of("USD", BigDecimal.ONE), givenBidRequest, banner, + "seat", "bidderName", null); @@ -193,7 +200,7 @@ public void resolveShouldApplyTwoCpmRules() { public void resolveShouldNotApplyAnyRulesWhenNoMatchFound() { // given final BidRequest givenBidRequest = BidRequest.builder().build(); - given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "bidderName", null)) + given(bidAdjustmentsRulesResolver.resolve(givenBidRequest, banner, "seat", "bidderName", null)) .willReturn(Collections.emptyList()); // when @@ -201,6 +208,7 @@ public void resolveShouldNotApplyAnyRulesWhenNoMatchFound() { Price.of("USD", BigDecimal.ONE), BidRequest.builder().build(), banner, + "seat", "bidderName", null); diff --git a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsRulesResolverTest.java b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsRulesResolverTest.java index 1b35b34a273..2c85847fd63 100644 --- a/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsRulesResolverTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/BidAdjustmentsRulesResolverTest.java @@ -58,6 +58,7 @@ public void resolveShouldPickAndApplyRulesBySpecificMediaType() throws JsonProce final List actual = target.resolve( givenBidRequest(givenAdjustments), ImpMediaType.banner, + "seat", "bidderName", "dealId"); @@ -101,6 +102,7 @@ public void resolveShouldPickAndApplyRulesByWildcardMediaType() throws JsonProce final List actual = target.resolve( givenBidRequest(givenAdjustments), ImpMediaType.video_outstream, + "seat", "bidderName", "dealId"); @@ -140,6 +142,7 @@ public void resolveShouldPickAndApplyRulesBySpecificBidder() throws JsonProcessi final List actual = target.resolve( givenBidRequest(givenAdjustments), ImpMediaType.banner, + "seat", "bidderName", "dealId"); @@ -189,6 +192,7 @@ public void resolveShouldPickAndApplyRulesByWildcardBidder() throws JsonProcessi final List actual = target.resolve( givenBidRequest(givenAdjustments), ImpMediaType.banner, + "seat", "anotherBidderName", "dealId"); @@ -238,6 +242,7 @@ public void resolveShouldPickAndApplyRulesBySpecificDealId() throws JsonProcessi final List actual = target.resolve( givenBidRequest(givenAdjustments), ImpMediaType.banner, + "seat", "bidderName", "dealId"); @@ -285,6 +290,7 @@ public void resolveShouldPickAndApplyRulesByWildcardDealId() throws JsonProcessi final List actual = target.resolve( givenBidRequest(givenAdjustments), ImpMediaType.banner, + "seat", "bidderName", "anotherDealId"); @@ -334,6 +340,7 @@ public void resolveShouldPickAndApplyRulesByWildcardDealIdWhenDealIdIsNull() thr final List actual = target.resolve( givenBidRequest(givenAdjustments), ImpMediaType.banner, + "seat", "bidderName", null); @@ -366,6 +373,7 @@ public void resolveShouldReturnEmptyListWhenNoMatchFound() throws JsonProcessing final List actual = target.resolve( givenBidRequest(givenAdjustments), ImpMediaType.banner, + "seat", "bidderName", null); @@ -373,6 +381,287 @@ public void resolveShouldReturnEmptyListWhenNoMatchFound() throws JsonProcessing assertThat(actual).isEmpty(); } + @Test + public void resolveShouldPickAndApplyRulesBySpecificSeat() throws JsonProcessingException { + // given + final String givenAdjustments = """ + { + "mediatype": { + "*": { + "seat": { + "*": [ + { + "adjtype": "multiplier", + "value": "15" + } + ] + }, + "*": { + "*": [ + { + "adjtype": "multiplier", + "value": "25" + } + ] + } + } + } + } + """; + + // when + final List actual = target.resolve( + givenBidRequest(givenAdjustments), + ImpMediaType.banner, + "seat", + "bidderName", + null); + + // then + assertThat(actual).containsExactly(expectedMultiplier("15")); + } + + @Test + public void resolveShouldPickAndApplyRulesByWildcardSeat() throws JsonProcessingException { + // given + final String givenAdjustments = """ + { + "mediatype": { + "*": { + "seat": { + "*": [ + { + "adjtype": "static", + "value": "15", + "currency": "EUR" + }, + { + "adjtype": "multiplier", + "value": "15" + } + ] + }, + "*": { + "*": [ + { + "adjtype": "static", + "value": "25", + "currency": "UAH" + }, + { + "adjtype": "multiplier", + "value": "25" + } + ] + } + } + } + } + """; + + // when + final List actual = target.resolve( + givenBidRequest(givenAdjustments), + ImpMediaType.banner, + "anotherBidderName", + "anotherSeat", + "dealId"); + + // then + assertThat(actual).containsExactly(expectedStatic("25", "UAH"), expectedMultiplier("25")); + } + + @Test + public void resolveShouldPickAndApplyRulesBySpecificBidderOverAbsentSeat() throws JsonProcessingException { + // given + final String givenAdjustments = """ + { + "mediatype": { + "*": { + "bidderName": { + "*": [ + { + "adjtype": "multiplier", + "value": "15" + } + ] + }, + "*": { + "*": [ + { + "adjtype": "multiplier", + "value": "25" + } + ] + } + } + } + } + """; + + // when + final List actual = target.resolve( + givenBidRequest(givenAdjustments), + ImpMediaType.banner, + "bidderName", + "seat", + "dealId"); + + // then + assertThat(actual).containsExactly(expectedMultiplier("15")); + } + + @Test + public void resolveShouldPickAndApplyRulesBySpecificBidderCaseInsensitive() throws JsonProcessingException { + // given + final String givenAdjustments = """ + { + "mediatype": { + "*": { + "BIDDERname": { + "*": [ + { + "adjtype": "multiplier", + "value": "15" + } + ] + }, + "*": { + "*": [ + { + "adjtype": "multiplier", + "value": "25" + } + ] + } + } + } + } + """; + + // when + final List actual = target.resolve( + givenBidRequest(givenAdjustments), + ImpMediaType.banner, + "bidderName", + "seat", + "dealId"); + + // then + assertThat(actual).containsExactly(expectedMultiplier("15")); + } + + @Test + public void resolveShouldPickAndApplyRulesBySpecificSeatOverSpecificBidder() throws JsonProcessingException { + // given + final String givenAdjustments = """ + { + "mediatype": { + "*": { + "bidderName": { + "*": [ + { + "adjtype": "static", + "value": "15", + "currency": "EUR" + }, + { + "adjtype": "multiplier", + "value": "15" + } + ] + }, + "seat": { + "*": [ + { + "adjtype": "static", + "value": "25", + "currency": "UAH" + }, + { + "adjtype": "multiplier", + "value": "25" + } + ] + } + } + } + } + """; + + // when + final List actual = target.resolve( + givenBidRequest(givenAdjustments), + ImpMediaType.banner, + "seat", + "bidderName", + "dealId"); + + // then + assertThat(actual).containsExactly(expectedStatic("25", "UAH"), expectedMultiplier("25")); + } + + @Test + public void resolveShouldPickAndApplyMoreSpecificRuleOverLessSpecific() throws JsonProcessingException { + // given + final String givenAdjustments = """ + { + "mediatype": { + "banner": { + "bidderName": { + "*": [ + { + "adjtype": "static", + "value": "15", + "currency": "EUR" + }, + { + "adjtype": "multiplier", + "value": "15" + } + ], + "dealId": [ + { + "adjtype": "static", + "value": "25", + "currency": "EUR" + }, + { + "adjtype": "multiplier", + "value": "25" + } + ] + }, + "seat": { + "*": [ + { + "adjtype": "static", + "value": "35", + "currency": "UAH" + }, + { + "adjtype": "multiplier", + "value": "35" + } + ] + } + } + } + } + """; + + // when + final List actual = target.resolve( + givenBidRequest(givenAdjustments), + ImpMediaType.banner, + "bidderName", + "seat", + "dealId"); + + // then + assertThat(actual).containsExactly(expectedStatic("25", "EUR"), expectedMultiplier("25")); + } + private static BidRequest givenBidRequest(String adjustmentsString) throws JsonProcessingException { final ObjectNode adjustmetsNode = (ObjectNode) mapper.readTree(adjustmentsString); return BidRequest.builder() diff --git a/src/test/java/org/prebid/server/bidadjustments/FloorAdjustmentsResolverTest.java b/src/test/java/org/prebid/server/bidadjustments/FloorAdjustmentsResolverTest.java index 14ea44e59dd..1cfb5dbe848 100644 --- a/src/test/java/org/prebid/server/bidadjustments/FloorAdjustmentsResolverTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/FloorAdjustmentsResolverTest.java @@ -14,10 +14,10 @@ import org.prebid.server.proto.openrtb.ext.request.ImpMediaType; import java.math.BigDecimal; -import java.util.Collections; import java.util.List; import java.util.Set; +import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -63,10 +63,8 @@ public void resolveShouldReturnInitialPriceWhenNoRulesFoundForAnyMediaType() { final BidRequest bidRequest = givenBidRequest(USD); final Set mediaTypes = Set.of(banner, video_outstream); - given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME, null)) - .willReturn(Collections.emptyList()); - given(bidAdjustmentsRulesResolver.resolve(bidRequest, video_outstream, BIDDER_NAME, null)) - .willReturn(Collections.emptyList()); + given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME)).willReturn(emptyList()); + given(bidAdjustmentsRulesResolver.resolve(bidRequest, video_outstream, BIDDER_NAME)).willReturn(emptyList()); given(currencyService.convertCurrency(BigDecimal.TEN, bidRequest, USD, USD)).willReturn(BigDecimal.TEN); // when @@ -87,7 +85,7 @@ public void resolveShouldApplyMultiplierRuleInReverse() { final BidAdjustmentsRule multiplierRule = givenMultiplier("2"); - given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME, null)) + given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME)) .willReturn(singletonList(multiplierRule)); given(currencyService.convertCurrency(eq(new BigDecimal("10.0000")), eq(bidRequest), eq(USD), eq(USD))) .willReturn(BigDecimal.valueOf(20)); @@ -111,8 +109,7 @@ public void resolveShouldApplyCpmRuleInReverse() { final BidAdjustmentsRule cpmRule = givenCpm("5", EUR); - given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME, null)) - .willReturn(singletonList(cpmRule)); + given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME)).willReturn(singletonList(cpmRule)); given(currencyService.convertCurrency(new BigDecimal("5"), bidRequest, EUR, USD)) .willReturn(BigDecimal.valueOf(0.5)); given(currencyService.convertCurrency(new BigDecimal("50.5"), bidRequest, USD, USD)) @@ -138,7 +135,7 @@ public void resolveShouldThrowExceptionWhenStaticRuleIsEncountered() { final BidAdjustmentsRule staticRule = givenStatic("5", USD); - given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME, null)) + given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME)) .willReturn(singletonList(staticRule)); // when and then @@ -159,8 +156,7 @@ public void resolveShouldApplyMultipleRulesInReverseOrder() { final BidAdjustmentsRule rule1 = givenMultiplier("2"); final BidAdjustmentsRule rule2 = givenCpm("5", EUR); - given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME, null)) - .willReturn(List.of(rule1, rule2)); + given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME)).willReturn(List.of(rule1, rule2)); given(currencyService.convertCurrency(new BigDecimal("5"), bidRequest, EUR, USD)) .willReturn(BigDecimal.valueOf(0.5)); given(currencyService.convertCurrency(new BigDecimal("50.2500"), bidRequest, USD, USD)) @@ -184,11 +180,11 @@ public void resolveShouldChooseMinimalFloorAcrossMediaTypesAfterConversion() { final Set mediaTypes = Set.of(banner, video_outstream); final BidAdjustmentsRule bannerRule = givenMultiplier("4"); - given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME, null)) + given(bidAdjustmentsRulesResolver.resolve(bidRequest, banner, BIDDER_NAME)) .willReturn(singletonList(bannerRule)); final BidAdjustmentsRule videoRule = givenCpm("500", UAH); - given(bidAdjustmentsRulesResolver.resolve(bidRequest, video_outstream, BIDDER_NAME, null)) + given(bidAdjustmentsRulesResolver.resolve(bidRequest, video_outstream, BIDDER_NAME)) .willReturn(singletonList(videoRule)); given(currencyService.convertCurrency(new BigDecimal("25.0000"), bidRequest, USD, EUR)) diff --git a/src/test/java/org/prebid/server/bidadjustments/model/BidAdjustmentsRulesTest.java b/src/test/java/org/prebid/server/bidadjustments/model/BidAdjustmentsRulesTest.java index 45de1a0c64c..35afb5ca46d 100644 --- a/src/test/java/org/prebid/server/bidadjustments/model/BidAdjustmentsRulesTest.java +++ b/src/test/java/org/prebid/server/bidadjustments/model/BidAdjustmentsRulesTest.java @@ -1,5 +1,6 @@ package org.prebid.server.bidadjustments.model; +import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.junit.jupiter.api.Test; import java.math.BigDecimal; @@ -38,7 +39,7 @@ public void shouldBuildRulesSet() { final BidAdjustmentsRules actual = BidAdjustmentsRules.of(givenBidAdjustments); // then - final BidAdjustmentsRules expected = BidAdjustmentsRules.of(Map.of( + final BidAdjustmentsRules expected = BidAdjustmentsRules.of(new CaseInsensitiveMap<>(Map.of( "audio|bidderName|dealId", givenRules, "native|bidderName|dealId", givenRules, "video-instream|bidderName|dealId", givenRules, @@ -46,10 +47,9 @@ public void shouldBuildRulesSet() { "banner|bidderName|dealId", givenRules, "*|*|*", givenRules, "*|bidderName|*", givenRules, - "*|bidderName|dealId", givenRules)); + "*|bidderName|dealId", givenRules))); assertThat(actual).isEqualTo(expected); - } private static BidAdjustmentsRule givenRule(String value) {