Skip to content

Commit

Permalink
Adkernel: Bid type resolving update (#3331)
Browse files Browse the repository at this point in the history
  • Loading branch information
SerhiiNahornyi authored Jul 30, 2024
1 parent b9a0c44 commit febfa08
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 126 deletions.
46 changes: 13 additions & 33 deletions src/main/java/org/prebid/server/bidder/adkernel/AdkernelBidder.java
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,7 @@ private static BidderBid makeBidderBid(Bid bid, List<Imp> imps, String currency)
final Optional<String> mfSuffix = getMfSuffix(bid.getImpid());
final Bid updatedBid = mfSuffix.map(suffix -> removeMfSuffixFromImpId(bid, suffix)).orElse(bid);

final BidType bidType = mfSuffix
.flatMap(AdkernelBidder::getTypeFromMsSuffix)
.orElseGet(() -> getTypeFromImp(updatedBid.getImpid(), imps));

return BidderBid.of(updatedBid, bidType, currency);
return BidderBid.of(updatedBid, getBidType(bid), currency);
}

private static Optional<String> getMfSuffix(String impId) {
Expand All @@ -265,35 +261,19 @@ private static Bid removeMfSuffixFromImpId(Bid bid, String mfSuffix) {
.build();
}

private static Optional<BidType> getTypeFromMsSuffix(String msSuffix) {
final BidType bidType = switch (msSuffix) {
case MF_SUFFIX_BANNER -> BidType.banner;
case MF_SUFFIX_VIDEO -> BidType.video;
case MF_SUFFIX_AUDIO -> BidType.audio;
case MF_SUFFIX_NATIVE -> BidType.xNative;
default -> null;
};

return Optional.ofNullable(bidType);
}

private static BidType getTypeFromImp(String impId, List<Imp> imps) {
for (Imp imp : imps) {
if (!imp.getId().equals(impId)) {
continue;
}

if (imp.getBanner() != null) {
return BidType.banner;
} else if (imp.getVideo() != null) {
return BidType.video;
} else if (imp.getAudio() != null) {
return BidType.audio;
} else if (imp.getXNative() != null) {
return BidType.xNative;
}
private static BidType getBidType(Bid bid) {
final Integer markupType = bid.getMtype();
if (markupType == null) {
throw new PreBidException("Missing MType for bid: " + bid.getId());
}

return BidType.video;
return switch (markupType) {
case 1 -> BidType.banner;
case 2 -> BidType.video;
case 3 -> BidType.audio;
case 4 -> BidType.xNative;
default -> throw new PreBidException(
"Unsupported MType %d".formatted(markupType));
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
import io.vertx.core.http.HttpMethod;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.prebid.server.VertxTest;
import org.prebid.server.bidder.model.BidderBid;
Expand Down Expand Up @@ -284,172 +285,121 @@ public void makeBidsShouldReturnErrorWhenSeatBidsCountIsNotOne() throws JsonProc
}

@Test
public void makeBidsShouldResolveBidTypeFromMfSuffixWhenPresent() throws JsonProcessingException {
public void makeBidsShouldResolveBidTypeToBannerWhenMTypeIsOne() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidRequest(
identity(),
impBuilder -> impBuilder.id("123").banner(Banner.builder().build())
.video(Video.builder().build())),
mapper.writeValueAsString(
givenBidResponse(
bidBuilder -> bidBuilder.impid("123b__mf"),
bidBuilder -> bidBuilder.impid("123v__mf"),
bidBuilder -> bidBuilder.impid("123a__mf"),
bidBuilder -> bidBuilder.impid("123n__mf"))));
givenBidResponse(bidBuilder -> bidBuilder.mtype(1).impid("123b__mf")));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue())
.containsExactlyInAnyOrder(
BidderBid.of(Bid.builder().impid("123").build(), banner, "USD"),
BidderBid.of(Bid.builder().impid("123").build(), video, "USD"),
BidderBid.of(Bid.builder().impid("123").build(), audio, "USD"),
BidderBid.of(Bid.builder().impid("123").build(), xNative, "USD"));
.extracting(BidderBid::getType)
.containsExactly(banner);
}

@Test
public void makeBidsShouldResolveVideoBidTypeFromImpWhenMfSuffixIsAbsentAndVideoPresentInRequestImp()
throws JsonProcessingException {

// given
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidRequest(
identity(),
impBuilder -> impBuilder
.id("123")
.video(Video.builder().build())
.banner(null)
.audio(null)
.xNative(null)),
mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).containsExactly(
BidderBid.of(Bid.builder().impid("123").build(), video, "USD"));
}

@Test
public void makeBidsShouldResolveBannerBidTypeFromImpWhenMfSuffixIsAbsentAndBannerPresentInRequestImp()
throws JsonProcessingException {

public void makeBidsShouldResolveBidTypeToVideoWhenMTypeIsTwo() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidRequest(
identity(),
impBuilder -> impBuilder
.id("123")
.video(null)
.banner(Banner.builder().build())
.audio(null)
.xNative(null)),
mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));
impBuilder -> impBuilder.id("123").banner(Banner.builder().build())
.video(Video.builder().build())),
givenBidResponse(bidBuilder -> bidBuilder.mtype(2).impid("123b__mf")));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).containsExactly(
BidderBid.of(Bid.builder().impid("123").build(), banner, "USD"));
assertThat(result.getValue())
.extracting(BidderBid::getType)
.containsExactly(video);
}

@Test
public void makeBidsShouldResolveAudioBidTypeFromImpWhenMfSuffixIsAbsentAndAudioPresentInRequestImp()
throws JsonProcessingException {

public void makeBidsShouldResolveBidTypeToAudioWhenMTypeIsThree() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidRequest(
identity(),
impBuilder -> impBuilder
.id("123")
.video(null)
.banner(null)
.audio(Audio.builder().build())
.xNative(null)),
mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));
impBuilder -> impBuilder.id("123").banner(Banner.builder().build())
.video(Video.builder().build())),
givenBidResponse(bidBuilder -> bidBuilder.mtype(3).impid("123b__mf")));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).containsExactly(
BidderBid.of(Bid.builder().impid("123").build(), audio, "USD"));
assertThat(result.getValue())
.extracting(BidderBid::getType)
.containsExactly(audio);
}

@Test
public void makeBidsShouldResolveNativeBidTypeFromImpWhenMfSuffixIsAbsentAndNativePresentInRequestImp()
throws JsonProcessingException {

public void makeBidsShouldResolveBidTypeToNativeWhenMTypeIsFour() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidRequest(
identity(),
impBuilder -> impBuilder
.id("123")
.video(null)
.banner(null)
.audio(null)
.xNative(Native.builder().build())),
mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));
impBuilder -> impBuilder.id("123").banner(Banner.builder().build())
.video(Video.builder().build())),
givenBidResponse(bidBuilder -> bidBuilder.mtype(4).impid("123b__mf")));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).containsExactly(
BidderBid.of(Bid.builder().impid("123").build(), xNative, "USD"));
assertThat(result.getValue())
.extracting(BidderBid::getType)
.containsExactly(xNative);
}

@Test
public void makeBidsShouldReturnVideoBid() throws JsonProcessingException {
public void makeBidsShouldReturnErrorIfMtypeIsMissing() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidRequest(
identity(),
impBuilder -> impBuilder.id("123")
impBuilder -> impBuilder.id("123").banner(Banner.builder().build())
.video(Video.builder().build())),
mapper.writeValueAsString(
givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));
givenBidResponse(bidBuilder -> bidBuilder.id("bidId").mtype(null).impid("123b__mf")));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue())
.containsExactly(BidderBid.of(Bid.builder().impid("123").build(), video, "USD"));
assertThat(result.getErrors())
.containsExactly(BidderError.badServerResponse("Missing MType for bid: bidId"));
assertThat(result.getValue()).isEmpty();
}

@Test
public void makeBidsShouldReturnBannerBidIfRequestImpHasBanner() throws JsonProcessingException {
public void makeBidsShouldReturnErrorIfMtypeIsNotValid() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = givenHttpCall(
givenBidRequest(
identity(),
builder -> builder.id("123")
.video(Video.builder().build())
.banner(Banner.builder().build())),
mapper.writeValueAsString(
givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));
impBuilder -> impBuilder.id("123").banner(Banner.builder().build())
.video(Video.builder().build())),
givenBidResponse(bidBuilder -> bidBuilder.id("bidId").mtype(10).impid("123b__mf")));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue())
.containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD"));
assertThat(result.getErrors())
.containsExactly(BidderError.badServerResponse("Unsupported MType 10"));
assertThat(result.getValue()).isEmpty();
}

@SafeVarargs
Expand Down Expand Up @@ -477,15 +427,16 @@ private static ObjectNode givenImpExt(Integer zoneId) {
}

@SafeVarargs
private static BidResponse givenBidResponse(UnaryOperator<Bid.BidBuilder>... bidCustomizers) {
return BidResponse.builder()
@SneakyThrows
private String givenBidResponse(UnaryOperator<Bid.BidBuilder>... bidCustomizers) {
return mapper.writeValueAsString(BidResponse.builder()
.cur("USD")
.seatbid(singletonList(SeatBid.builder()
.bid(Arrays.stream(bidCustomizers)
.map(bidCustomizer -> bidCustomizer.apply(Bid.builder()).build())
.toList())
.build()))
.build();
.build());
}

private static BidderCall<BidRequest> givenHttpCall(BidRequest bidRequest, String body) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"crid": "2002",
"adid": "2002",
"adm": "<!-- admarkup -->",
"mtype": 1,
"adomain": [
"tag-example.com"
]
Expand All @@ -19,4 +20,4 @@
}
],
"bidid": "bid_id"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
],
"cid": "1001",
"crid": "2002",
"mtype": 1,
"ext": {
"prebid": {
"type": "banner"
Expand Down

0 comments on commit febfa08

Please sign in to comment.