From 0f803014aee7fa6c5d04354b75cead09ba53c9ad Mon Sep 17 00:00:00 2001 From: Anton Babak <76536883+AntoxaAntoxic@users.noreply.github.com> Date: Tue, 14 Nov 2023 11:20:07 +0100 Subject: [PATCH] Pubmatic: Support fledge (#2732) --- .../bidder/pubmatic/PubmaticBidder.java | 51 ++++-- .../model/request/PubmaticBidderImpExt.java | 7 +- .../model/response/PubmaticBidResponse.java | 27 +++ .../response/PubmaticExtBidResponse.java | 15 ++ .../bidder/pubmatic/PubmaticBidderTest.java | 154 +++++++++++++----- .../test-auction-pubmatic-request.json | 3 +- .../test-auction-pubmatic-response.json | 2 +- .../pubmatic/test-pubmatic-bid-request.json | 3 +- .../pubmatic/test-pubmatic-bid-response.json | 4 +- 9 files changed, 206 insertions(+), 60 deletions(-) create mode 100644 src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticBidResponse.java create mode 100644 src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticExtBidResponse.java diff --git a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java index a1ff1f7f716..663048b76b5 100644 --- a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java +++ b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java @@ -11,7 +11,6 @@ import com.iab.openrtb.request.Publisher; import com.iab.openrtb.request.Site; import com.iab.openrtb.response.Bid; -import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; @@ -20,6 +19,7 @@ import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.CompositeBidderResponse; import org.prebid.server.bidder.model.HttpRequest; import org.prebid.server.bidder.model.Result; import org.prebid.server.bidder.pubmatic.model.request.PubmaticBidderImpExt; @@ -27,6 +27,8 @@ import org.prebid.server.bidder.pubmatic.model.request.PubmaticExtDataAdServer; import org.prebid.server.bidder.pubmatic.model.request.PubmaticWrapper; import org.prebid.server.bidder.pubmatic.model.response.PubmaticBidExt; +import org.prebid.server.bidder.pubmatic.model.response.PubmaticBidResponse; +import org.prebid.server.bidder.pubmatic.model.response.PubmaticExtBidResponse; import org.prebid.server.bidder.pubmatic.model.response.VideoCreativeInfo; import org.prebid.server.exception.PreBidException; import org.prebid.server.json.DecodeException; @@ -37,6 +39,7 @@ 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.ExtBidPrebidVideo; +import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; @@ -61,6 +64,7 @@ public class PubmaticBidder implements Bidder { private static final String ACAT_EXT_REQUEST = "acat"; private static final String WRAPPER_EXT_REQUEST = "wrapper"; private static final String BIDDER_NAME = "pubmatic"; + private static final String AE = "ae"; private final String endpointUrl; private final JacksonMapper mapper; @@ -180,17 +184,20 @@ private PubmaticBidderImpExt parseImpExt(Imp imp) { private Imp modifyImp(Imp imp, PubmaticBidderImpExt impExt) { final Banner banner = imp.getBanner(); - final ObjectNode keywordsNode = makeKeywords(impExt); final ExtImpPubmatic impExtBidder = impExt.getBidder(); + final ObjectNode modifiedExt = makeKeywords(impExt); + if (impExt.getAe() != null) { + modifiedExt.put(AE, impExt.getAe()); + } + final Imp.ImpBuilder impBuilder = imp.toBuilder() .banner(banner != null ? assignSizesIfMissing(banner) : null) - .ext(!keywordsNode.isEmpty() ? keywordsNode : null) + .ext(!modifiedExt.isEmpty() ? modifiedExt : null) .bidfloor(resolveBidFloor(impExtBidder.getKadfloor(), imp.getBidfloor())) .audio(null); - return enrichWithAdSlotParameters(impBuilder, impExtBidder.getAdSlot(), banner) - .build(); + return enrichWithAdSlotParameters(impBuilder, impExtBidder.getAdSlot(), banner).build(); } private BigDecimal resolveBidFloor(String kadfloor, BigDecimal existingFloor) { @@ -365,24 +372,35 @@ private static Publisher modifyPublisher(Publisher publisher, String publisherId : Publisher.builder().id(publisherId).build(); } + /** + * @deprecated for this bidder in favor of @link{makeBidderResponse} which supports additional response data + */ @Override - public final Result> makeBids(BidderCall httpCall, BidRequest bidRequest) { + @Deprecated(forRemoval = true) + public Result> makeBids(BidderCall httpCall, BidRequest bidRequest) { + return Result.withError(BidderError.generic("Deprecated adapter method invoked")); + } + + @Override + public CompositeBidderResponse makeBidderResponse(BidderCall httpCall, BidRequest bidRequest) { try { final List bidderErrors = new ArrayList<>(); - final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); - return Result.of(extractBids(bidResponse, bidderErrors), Collections.emptyList()); + final PubmaticBidResponse bidResponse = mapper.decodeValue( + httpCall.getResponse().getBody(), + PubmaticBidResponse.class); + return CompositeBidderResponse.withBids(extractBids(bidResponse, bidderErrors), extractFledge(bidResponse)); } catch (DecodeException | PreBidException e) { - return Result.withError(BidderError.badServerResponse(e.getMessage())); + return CompositeBidderResponse.withError(BidderError.badServerResponse(e.getMessage())); } } - private List extractBids(BidResponse bidResponse, List bidderErrors) { + private List extractBids(PubmaticBidResponse bidResponse, List bidderErrors) { return bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid()) ? Collections.emptyList() : bidsFromResponse(bidResponse, bidderErrors); } - private List bidsFromResponse(BidResponse bidResponse, List bidderErrors) { + private List bidsFromResponse(PubmaticBidResponse bidResponse, List bidderErrors) { return bidResponse.getSeatbid().stream() .filter(Objects::nonNull) .map(SeatBid::getBid) @@ -473,4 +491,15 @@ private static Integer getDealPriority(PubmaticBidExt bidExt) { .map(PubmaticBidExt::getPrebidDealPriority) .orElse(null); } + + private static List extractFledge(PubmaticBidResponse bidResponse) { + return Optional.ofNullable(bidResponse) + .map(PubmaticBidResponse::getExt) + .map(PubmaticExtBidResponse::getFledgeAuctionConfigs) + .orElse(Collections.emptyMap()) + .entrySet() + .stream() + .map(e -> FledgeAuctionConfig.builder().impId(e.getKey()).config(e.getValue()).build()) + .toList(); + } } diff --git a/src/main/java/org/prebid/server/bidder/pubmatic/model/request/PubmaticBidderImpExt.java b/src/main/java/org/prebid/server/bidder/pubmatic/model/request/PubmaticBidderImpExt.java index ffb67603170..3da1ca136ab 100644 --- a/src/main/java/org/prebid/server/bidder/pubmatic/model/request/PubmaticBidderImpExt.java +++ b/src/main/java/org/prebid/server/bidder/pubmatic/model/request/PubmaticBidderImpExt.java @@ -1,14 +1,15 @@ package org.prebid.server.bidder.pubmatic.model.request; -import lombok.AllArgsConstructor; import lombok.Value; import org.prebid.server.proto.openrtb.ext.request.pubmatic.ExtImpPubmatic; -@AllArgsConstructor(staticName = "of") -@Value +@Value(staticConstructor = "of") public class PubmaticBidderImpExt { ExtImpPubmatic bidder; PubmaticExtData data; + + Integer ae; + } diff --git a/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticBidResponse.java b/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticBidResponse.java new file mode 100644 index 00000000000..b421e7f1b4a --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticBidResponse.java @@ -0,0 +1,27 @@ +package org.prebid.server.bidder.pubmatic.model.response; + +import com.iab.openrtb.response.SeatBid; +import lombok.Builder; +import lombok.Value; + +import java.util.List; + +@Builder(toBuilder = true) +@Value +public class PubmaticBidResponse { + + String id; + + List seatbid; + + String bidid; + + String cur; + + String customdata; + + Integer nbr; + + PubmaticExtBidResponse ext; + +} diff --git a/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticExtBidResponse.java b/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticExtBidResponse.java new file mode 100644 index 00000000000..d2c531a23b5 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/pubmatic/model/response/PubmaticExtBidResponse.java @@ -0,0 +1,15 @@ +package org.prebid.server.bidder.pubmatic.model.response; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Value; + +import java.util.Map; + +@Value(staticConstructor = "of") +public class PubmaticExtBidResponse { + + @JsonProperty("fledge_auction_configs") + Map fledgeAuctionConfigs; + +} diff --git a/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java b/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java index fe3958ecdc8..e12340fdfa7 100644 --- a/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java @@ -22,6 +22,7 @@ import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.CompositeBidderResponse; import org.prebid.server.bidder.model.HttpRequest; import org.prebid.server.bidder.model.HttpResponse; import org.prebid.server.bidder.model.Result; @@ -30,6 +31,8 @@ import org.prebid.server.bidder.pubmatic.model.request.PubmaticExtDataAdServer; import org.prebid.server.bidder.pubmatic.model.request.PubmaticWrapper; import org.prebid.server.bidder.pubmatic.model.response.PubmaticBidExt; +import org.prebid.server.bidder.pubmatic.model.response.PubmaticBidResponse; +import org.prebid.server.bidder.pubmatic.model.response.PubmaticExtBidResponse; import org.prebid.server.bidder.pubmatic.model.response.VideoCreativeInfo; import org.prebid.server.proto.openrtb.ext.ExtPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; @@ -38,6 +41,7 @@ import org.prebid.server.proto.openrtb.ext.request.pubmatic.ExtImpPubmaticKeyVal; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo; +import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import org.prebid.server.util.HttpUtil; import java.math.BigDecimal; @@ -525,7 +529,8 @@ public void makeHttpRequestsShouldAddImpExtAddUnitKeyKeyWordFromDataAdSlotIfAdSe .ext(mapper.valueToTree(PubmaticBidderImpExt.of( ExtImpPubmatic.builder().build(), PubmaticExtData.of("pbaAdSlot", - PubmaticExtDataAdServer.of("adServerName", "adServerAdSlot")) + PubmaticExtDataAdServer.of("adServerName", "adServerAdSlot")), + null ))) .build())) .build(); @@ -553,7 +558,8 @@ public void makeHttpRequestsShouldAddImpExtAddUnitKeyKeyWordFromAdServerAdSlotIf .banner(Banner.builder().build()) .ext(mapper.valueToTree(PubmaticBidderImpExt.of( ExtImpPubmatic.builder().build(), - PubmaticExtData.of("pbaAdSlot", PubmaticExtDataAdServer.of("gam", "adServerAdSlot")) + PubmaticExtData.of("pbaAdSlot", PubmaticExtDataAdServer.of("gam", "adServerAdSlot")), + null ))) .build())) .build(); @@ -572,6 +578,30 @@ public void makeHttpRequestsShouldAddImpExtAddUnitKeyKeyWordFromAdServerAdSlotIf .containsOnly(expectedImpExt); } + @Test + public void makeHttpRequestsShouldAddImpExtAddAE() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id("123") + .banner(Banner.builder().build()) + .ext(mapper.valueToTree(PubmaticBidderImpExt.of(ExtImpPubmatic.builder().build(), null, 1))) + .build())) + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedImpExt = mapper.createObjectNode().put("ae", 1); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsOnly(expectedImpExt); + } + @Test public void makeHttpRequestsShouldSetImpExtFromKeywordsSkippingKeysWithEmptyValues() { // given @@ -786,65 +816,65 @@ public void makeHttpRequestsShouldFillMethodAndUrlAndExpectedHeaders() { } @Test - public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { + public void makeBidderResponseShouldReturnErrorIfResponseBodyCouldNotBeParsed() { // given final BidderCall httpCall = givenHttpCall(null, "invalid"); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).hasSize(1); assertThat(result.getErrors().get(0).getMessage()).startsWith("Failed to decode: Unrecognized token"); assertThat(result.getErrors().get(0).getType()).isEqualTo(BidderError.Type.bad_server_response); - assertThat(result.getValue()).isEmpty(); + assertThat(result.getBids()).isEmpty(); } @Test - public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + public void makeBidderResponseShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString(null)); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).isEmpty(); + assertThat(result.getBids()).isEmpty(); } @Test - public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + public void makeBidderResponseShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString(BidResponse.builder().build())); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).isEmpty(); + assertThat(result.getBids()).isEmpty(); } @Test - public void makeBidsShouldReturnBannerBid() throws JsonProcessingException { + public void makeBidderResponseShouldReturnBannerBid() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) + assertThat(result.getBids()) .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); } @Test - public void makeBidsShouldReturnVideoBidIfExtBidContainsBidTypeOne() throws JsonProcessingException { + public void makeBidderResponseShouldReturnVideoBidIfExtBidContainsBidTypeOne() throws JsonProcessingException { // given final ObjectNode bidType = mapper.createObjectNode().put("BidType", 1); final BidderCall httpCall = givenHttpCall(null, @@ -852,16 +882,16 @@ public void makeBidsShouldReturnVideoBidIfExtBidContainsBidTypeOne() throws Json givenBidResponse(bidBuilder -> bidBuilder.impid("123").ext(bidType)))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) + assertThat(result.getBids()) .containsOnly(BidderBid.of(Bid.builder().impid("123").ext(bidType).build(), video, "USD")); } @Test - public void makeBidsShouldReturnXNativeBidIfExtBidContainsBidTypeTwo() throws JsonProcessingException { + public void makeBidderResponseShouldReturnXNativeBidIfExtBidContainsBidTypeTwo() throws JsonProcessingException { // given final ObjectNode bidType = mapper.createObjectNode().put("BidType", 2); final BidderCall httpCall = givenHttpCall(null, @@ -869,16 +899,17 @@ public void makeBidsShouldReturnXNativeBidIfExtBidContainsBidTypeTwo() throws Js givenBidResponse(bidBuilder -> bidBuilder.impid("123").ext(bidType)))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) + assertThat(result.getBids()) .containsOnly(BidderBid.of(Bid.builder().impid("123").ext(bidType).build(), xNative, "USD")); } @Test - public void makeBidsShouldFillExtBidPrebidVideoDurationIfDurationIsNotNull() throws JsonProcessingException { + public void makeBidderResponseShouldFillExtBidPrebidVideoDurationIfDurationIsNotNull() + throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString( @@ -887,7 +918,7 @@ public void makeBidsShouldFillExtBidPrebidVideoDurationIfDurationIsNotNull() thr PubmaticBidExt.of(null, VideoCreativeInfo.of(1), null)))))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); @@ -895,12 +926,13 @@ public void makeBidsShouldFillExtBidPrebidVideoDurationIfDurationIsNotNull() thr bidExt.set("video", mapper.valueToTree(VideoCreativeInfo.of(1))); bidExt.set("prebid", mapper.valueToTree(ExtBidPrebid.builder().video(ExtBidPrebidVideo.of(1, null)).build())); - assertThat(result.getValue()) + assertThat(result.getBids()) .containsOnly(BidderBid.of(Bid.builder().impid("123").ext(bidExt).build(), banner, "USD")); } @Test - public void makeBidsShouldNotFillExtBidPrebidVideoDurationIfDurationIsNull() throws JsonProcessingException { + public void makeBidderResponseShouldNotFillExtBidPrebidVideoDurationIfDurationIsNull() + throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString( @@ -909,19 +941,19 @@ public void makeBidsShouldNotFillExtBidPrebidVideoDurationIfDurationIsNull() thr PubmaticBidExt.of(null, VideoCreativeInfo.of(null), null)))))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); final ObjectNode bidExt = mapper.createObjectNode(); bidExt.set("video", mapper.valueToTree(VideoCreativeInfo.of(null))); - assertThat(result.getValue()) + assertThat(result.getBids()) .containsOnly(BidderBid.of(Bid.builder().impid("123").ext(bidExt).build(), banner, "USD")); } @Test - public void makeBidsShouldNotFillExtBidPrebidVideoDurationIfVideoIsNull() throws JsonProcessingException { + public void makeBidderResponseShouldNotFillExtBidPrebidVideoDurationIfVideoIsNull() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString( @@ -930,18 +962,18 @@ public void makeBidsShouldNotFillExtBidPrebidVideoDurationIfVideoIsNull() throws PubmaticBidExt.of(null, null, null)))))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) + assertThat(result.getBids()) .containsOnly(BidderBid.of(Bid.builder().impid("123").ext(mapper.createObjectNode()).build(), banner, "USD")); } @Test - public void makeBidsShouldFillDealPriorityData() throws JsonProcessingException { + public void makeBidderResponseShouldFillDealPriorityData() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString( @@ -950,18 +982,18 @@ public void makeBidsShouldFillDealPriorityData() throws JsonProcessingException PubmaticBidExt.of(null, null, 12)))))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) + assertThat(result.getBids()) .extracting(BidderBid::getDealPriority) .containsExactly(12); } @Test - public void makeBidsShouldParseNativeAdmData() throws JsonProcessingException { + public void makeBidderResponseShouldParseNativeAdmData() throws JsonProcessingException { // given final ObjectNode admNode = mapper.createObjectNode(); final ObjectNode nativeNode = mapper.createObjectNode(); @@ -975,19 +1007,19 @@ public void makeBidsShouldParseNativeAdmData() throws JsonProcessingException { PubmaticBidExt.of(2, null, 12)))))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) + assertThat(result.getBids()) .extracting(BidderBid::getBid) .extracting(Bid::getAdm) .containsExactly("{\"property1\":\"value1\"}"); } @Test - public void makeBidsShouldTakeOnlyFirstCatElement() throws JsonProcessingException { + public void makeBidderResponseShouldTakeOnlyFirstCatElement() throws JsonProcessingException { // given final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString( @@ -995,18 +1027,18 @@ public void makeBidsShouldTakeOnlyFirstCatElement() throws JsonProcessingExcepti .cat(asList("cat1", "cat2"))))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) + assertThat(result.getBids()) .containsOnly(BidderBid.of(Bid.builder().impid("123").cat(singletonList("cat1")).build(), banner, "USD")); } @Test - public void makeBidsShouldReturnBannerBidIfExtBidContainsIllegalBidType() throws JsonProcessingException { + public void makeBidderResponseShouldReturnBannerBidIfExtBidContainsIllegalBidType() throws JsonProcessingException { // given final ObjectNode bidType = mapper.createObjectNode().put("BidType", 100); final BidderCall httpCall = givenHttpCall(null, @@ -1014,14 +1046,54 @@ public void makeBidsShouldReturnBannerBidIfExtBidContainsIllegalBidType() throws givenBidResponse(bidBuilder -> bidBuilder.impid("123").ext(bidType)))); // when - final Result> result = target.makeBids(httpCall, null); + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) + assertThat(result.getBids()) .containsOnly(BidderBid.of(Bid.builder().impid("123").ext(bidType).build(), banner, "USD")); } + @Test + public void makeBidderResponseShouldReturnFledgeAuctionConfig() throws JsonProcessingException { + // given + final BidResponse bidResponse = givenBidResponse(bidBuilder -> bidBuilder.impid("imp_id")); + final ObjectNode fledgeAuctionConfig = mapper.createObjectNode(); + final PubmaticBidResponse bidResponseWithFledge = PubmaticBidResponse.builder() + .cur(bidResponse.getCur()) + .seatbid(bidResponse.getSeatbid()) + .ext(PubmaticExtBidResponse.of(Map.of("imp_id", fledgeAuctionConfig))) + .build(); + final BidderCall httpCall = givenHttpCall(null, mapper.writeValueAsString(bidResponseWithFledge)); + + // when + final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getBids()) + .containsOnly(BidderBid.of(Bid.builder().impid("imp_id").build(), banner, "USD")); + final FledgeAuctionConfig expectedFledge = FledgeAuctionConfig.builder() + .impId("imp_id") + .config(fledgeAuctionConfig) + .build(); + assertThat(result.getFledgeAuctionConfigs()).containsExactly(expectedFledge); + } + + @Test + public void makeBidsShouldFail() throws JsonProcessingException { + //given + final BidderCall httpCall = givenHttpCall( + null, + mapper.writeValueAsString(BidResponse.builder().build())); + + // when + final Result> result = target.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.generic("Deprecated adapter method invoked")); + } + @Test public void makeHttpRequestsShouldReplaceDctrIfPresent() { // given diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-request.json b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-request.json index 354b6d03cdc..4ce766dfbcc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-request.json @@ -2,7 +2,7 @@ "id": "request_id", "imp": [ { - "id": "imp_id", + "id": "test-imp-id", "video": { "mimes": [ "mimes" @@ -11,6 +11,7 @@ "h": 600 }, "ext": { + "ae": 1, "pubmatic": { "adSlot": "slot9@300x250:zzz", "publisherId": " publisherId ", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json index b6ed7f53ab3..53731b03bf0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json @@ -5,7 +5,7 @@ "bid": [ { "id": "bid_id", - "impid": "imp_id", + "impid": "test-imp-id", "price": 4.75, "adm": "adm9", "crid": "crid9", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-request.json index 7f5c25237fc..af44cdd81bf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-request.json @@ -2,7 +2,7 @@ "id": "request_id", "imp": [ { - "id": "imp_id", + "id": "test-imp-id", "secure": 1, "video": { "mimes": [ @@ -14,6 +14,7 @@ "tagid": "slot9", "bidfloor" : 0.12, "ext": { + "ae": 1, "pmZoneId": "Zone1,Zone2", "preference": "sports,movies", "dfp_ad_unit_code": "thirdPbAdSlot" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-response.json index 98e0881d3e8..713640bcf40 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-response.json @@ -5,7 +5,7 @@ "bid": [ { "id": "bid_id", - "impid": "imp_id", + "impid": "test-imp-id", "price": 4.75, "adm": "adm9", "crid": "crid9", @@ -20,4 +20,4 @@ "group": 0 } ] -} \ No newline at end of file +}