Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.prebid.server.bidder.insticator;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iab.openrtb.request.App;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Device;
Expand All @@ -10,7 +11,6 @@
import com.iab.openrtb.request.Video;
import com.iab.openrtb.response.Bid;
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
import io.vertx.core.MultiMap;
import org.apache.commons.collections4.CollectionUtils;
import org.prebid.server.bidder.Bidder;
Expand All @@ -28,13 +28,14 @@
import org.prebid.server.proto.openrtb.ext.request.ExtRequest;
import org.prebid.server.proto.openrtb.ext.request.insticator.ExtImpInsticator;
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 org.prebid.server.util.BidderUtil;
import org.prebid.server.util.HttpUtil;
import org.prebid.server.util.ObjectUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
Expand All @@ -49,6 +50,7 @@ public class InsticatorBidder implements Bidder<BidRequest> {

private static final String DEFAULT_BIDDER_CURRENCY = "USD";
private static final String INSTICATOR_FIELD = "insticator";
private static final String PREBID_FIELD = "prebid";
private static final InsticatorExtRequestCaller DEFAULT_INSTICATOR_CALLER =
InsticatorExtRequestCaller.of("Prebid-Server", "n/a");

Expand Down Expand Up @@ -241,22 +243,41 @@ public Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequ
}
}

private static List<BidderBid> extractBids(BidResponse bidResponse) {
private List<BidderBid> extractBids(BidResponse bidResponse) {
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) {
return Collections.emptyList();
}

return bidResponse.getSeatbid().stream()
.filter(Objects::nonNull)
.map(SeatBid::getBid)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.map(bid -> BidderBid.of(bid, getBidType(bid), bidResponse.getCur()))
.filter(Objects::nonNull)
.filter(seatBid -> CollectionUtils.isNotEmpty(seatBid.getBid()))
.flatMap(seatBid -> seatBid.getBid().stream()
.filter(Objects::nonNull)
.map(bid -> {
final BidType bidType = getBidType(bid);
return BidderBid.of(
modifyBidExt(bid, bidType, seatBid.getSeat()), bidType, bidResponse.getCur());
}))
.toList();
}

private Bid modifyBidExt(Bid bid, BidType bidType, String seat) {
final ExtBidPrebidMeta meta = ExtBidPrebidMeta.builder()
.mediaType(bidType.getName())
.seat(seat)
.build();
final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder()
.meta(meta)
.build();
final ObjectNode ext = bid.getExt() != null
? bid.getExt().deepCopy()
: mapper.mapper().createObjectNode();
ext.set(PREBID_FIELD, mapper.mapper().valueToTree(extBidPrebid));
return bid.toBuilder()
.ext(ext)
.build();
}

private static BidType getBidType(Bid bid) {
return switch (bid.getMtype()) {
case 2 -> BidType.video;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
import org.prebid.server.proto.openrtb.ext.request.ExtRequest;
import org.prebid.server.proto.openrtb.ext.request.insticator.ExtImpInsticator;
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.Arrays;
Expand Down Expand Up @@ -501,57 +503,107 @@ public void makeBidsShouldReturnEmptyBidsWhenResponseDoesNotHaveSeatBid() throws
@Test
public void makeBidsShouldReturnBannerBidSuccessfully() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(givenBidResponse(bid -> bid.impid("1").mtype(1)));
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidResponse(bid -> bid.impid("1").mtype(1), "dsp_seat"));

// when
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue())
.containsExactly(BidderBid.of(Bid.builder().mtype(1).impid("1").build(), banner, "USD"));
assertThat(result.getValue()).hasSize(1)
.allSatisfy(bidderBid -> {
assertThat(bidderBid.getType()).isEqualTo(banner);
assertThat(bidderBid.getBidCurrency()).isEqualTo("USD");
assertThat(bidderBid.getBid().getImpid()).isEqualTo("1");
});
assertThat(result.getValue().getFirst().getBid().getExt())
.isEqualTo(mapper.createObjectNode().set("prebid", mapper.valueToTree(
ExtBidPrebid.builder()
.meta(ExtBidPrebidMeta.builder()
.mediaType("banner")
.seat("dsp_seat")
.build())
.build())));
}

@Test
public void makeBidsShouldReturnVideoBidSuccessfully() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(givenBidResponse(bid -> bid.impid("2").mtype(2)));
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidResponse(bid -> bid.impid("2").mtype(2), "video_seat"));

// when
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue())
.containsExactly(BidderBid.of(Bid.builder().mtype(2).impid("2").build(), video, "USD"));
assertThat(result.getValue()).hasSize(1)
.allSatisfy(bidderBid -> {
assertThat(bidderBid.getType()).isEqualTo(video);
assertThat(bidderBid.getBidCurrency()).isEqualTo("USD");
assertThat(bidderBid.getBid().getImpid()).isEqualTo("2");
});
assertThat(result.getValue().getFirst().getBid().getExt())
.isEqualTo(mapper.createObjectNode().set("prebid", mapper.valueToTree(
ExtBidPrebid.builder()
.meta(ExtBidPrebidMeta.builder()
.mediaType("video")
.seat("video_seat")
.build())
.build())));
}

@Test
public void makeBidsShouldReturnBannerBidWhenMtypeIsUnknown() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(givenBidResponse(bid -> bid.impid("3").mtype(3)));
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidResponse(bid -> bid.impid("3").mtype(3), "seat1"));

// when
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue())
.containsExactly(BidderBid.of(Bid.builder().mtype(3).impid("3").build(), banner, "USD"));
assertThat(result.getValue()).hasSize(1)
.allSatisfy(bidderBid -> {
assertThat(bidderBid.getType()).isEqualTo(banner);
assertThat(bidderBid.getBid().getImpid()).isEqualTo("3");
});
}

@Test
public void makeBidsShouldReturnBannerBidWhenMtypeIsNull() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(givenBidResponse(bid -> bid.impid("3").mtype(null)));
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidResponse(bid -> bid.impid("3").mtype(null), null));

// when
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue())
.containsExactly(BidderBid.of(Bid.builder().mtype(null).impid("3").build(), banner, "USD"));
assertThat(result.getValue()).hasSize(1)
.allSatisfy(bidderBid -> {
assertThat(bidderBid.getType()).isEqualTo(banner);
assertThat(bidderBid.getBid().getImpid()).isEqualTo("3");
});
}

@Test
public void makeBidsShouldSetSeatFromSeatBidInMeta() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidResponse(bid -> bid.impid("1").mtype(1), "pubmatic_54229"));

// when
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).isEmpty();
final ObjectNode ext = result.getValue().getFirst().getBid().getExt();
final ExtBidPrebid extBidPrebid = mapper.treeToValue(ext.get("prebid"), ExtBidPrebid.class);
assertThat(extBidPrebid.getMeta().getSeat()).isEqualTo("pubmatic_54229");
}

private static BidRequest givenBidRequest(UnaryOperator<Imp.ImpBuilder>... impCustomizers) {
Expand Down Expand Up @@ -595,10 +647,16 @@ private static BidderCall<BidRequest> givenHttpCall(String body) {
}

private String givenBidResponse(UnaryOperator<Bid.BidBuilder> bidCustomizer) throws JsonProcessingException {
return givenBidResponse(bidCustomizer, null);
}

private String givenBidResponse(UnaryOperator<Bid.BidBuilder> bidCustomizer, String seat)
throws JsonProcessingException {
return mapper.writeValueAsString(BidResponse.builder()
.cur("USD")
.seatbid(singletonList(SeatBid.builder()
.bid(singletonList(bidCustomizer.apply(Bid.builder()).build()))
.seat(seat)
.build()))
.build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
"prebid": {
"type": "banner",
"meta": {
"adaptercode": "insticator"
"adaptercode": "insticator",
"mediaType": "banner",
"seat": "dsp_seat"
}
},
"origbidcpm": 3.33
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"h": 250,
"w": 300
}
]
],
"seat": "dsp_seat"
}
]
}
Loading