Skip to content

Commit

Permalink
Adnuntius: Fix impId resolution (#1867)
Browse files Browse the repository at this point in the history
  • Loading branch information
And1sS authored May 17, 2022
1 parent 6c34ce7 commit 641912e
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import io.vertx.core.MultiMap;
import io.vertx.core.http.HttpMethod;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.prebid.server.bidder.Bidder;
Expand All @@ -22,6 +21,7 @@
import org.prebid.server.bidder.adnuntius.model.response.AdnuntiusAdsUnit;
import org.prebid.server.bidder.adnuntius.model.response.AdnuntiusBid;
import org.prebid.server.bidder.adnuntius.model.response.AdnuntiusResponse;
import org.prebid.server.bidder.adnuntius.model.util.AdsUnitWithImpId;
import org.prebid.server.bidder.model.BidderBid;
import org.prebid.server.bidder.model.BidderError;
import org.prebid.server.bidder.model.HttpCall;
Expand Down Expand Up @@ -49,6 +49,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class AdnuntiusBidder implements Bidder<AdnuntiusRequest> {

Expand Down Expand Up @@ -192,44 +193,54 @@ public Result<List<BidderBid>> makeBids(HttpCall<AdnuntiusRequest> httpCall, Bid
try {
final String body = httpCall.getResponse().getBody();
final AdnuntiusResponse bidResponse = mapper.decodeValue(body, AdnuntiusResponse.class);
return Result.withValues(extractBids(bidResponse));
return Result.withValues(extractBids(bidRequest, bidResponse));
} catch (DecodeException | PreBidException e) {
return Result.withError(BidderError.badServerResponse(e.getMessage()));
}
}

private static List<BidderBid> extractBids(AdnuntiusResponse bidResponse) {
private static List<BidderBid> extractBids(BidRequest bidRequest, AdnuntiusResponse bidResponse) {
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getAdsUnits())) {
return Collections.emptyList();
}

final List<AdnuntiusAdsUnit> validAdsUnits = bidResponse.getAdsUnits().stream()
.filter(AdnuntiusBidder::validateAdsUnit).collect(Collectors.toList());
final List<AdnuntiusAdsUnit> adsUnits = bidResponse.getAdsUnits();
final List<Imp> imps = bidRequest.getImp();
if (adsUnits.size() > imps.size()) {
throw new PreBidException("Impressions count is less then ads units count.");
}

final List<AdsUnitWithImpId> validAdsUnitToImpId = IntStream.range(0, adsUnits.size())
.mapToObj(i -> AdsUnitWithImpId.of(adsUnits.get(i), imps.get(i).getId()))
.filter(adsUnitWithImpId -> validateAdsUnit(adsUnitWithImpId.getAdsUnit()))
.collect(Collectors.toList());

if (validAdsUnits.isEmpty()) {
if (validAdsUnitToImpId.isEmpty()) {
return Collections.emptyList();
}

final String currency = extractCurrency(validAdsUnits);
return validAdsUnits.stream().map(adsUnit -> makeBid(adsUnit, currency)).collect(Collectors.toList());
final String currency = extractCurrency(validAdsUnitToImpId);
return validAdsUnitToImpId.stream()
.map(adsUnitWithImpId -> makeBid(adsUnitWithImpId.getAdsUnit(), adsUnitWithImpId.getImpId(), currency))
.collect(Collectors.toList());
}

private static boolean validateAdsUnit(AdnuntiusAdsUnit adsUnit) {
final List<AdnuntiusAd> ads = ObjectUtil.getIfNotNull(adsUnit, AdnuntiusAdsUnit::getAds);
return CollectionUtils.isNotEmpty(ads) && ads.get(0) != null;
}

private static String extractCurrency(List<AdnuntiusAdsUnit> adsUnits) {
final AdnuntiusBid bid = adsUnits.get(adsUnits.size() - 1).getAds().get(0).getBid();
private static String extractCurrency(List<AdsUnitWithImpId> adsUnits) {
final AdnuntiusBid bid = adsUnits.get(adsUnits.size() - 1).getAdsUnit().getAds().get(0).getBid();
return ObjectUtil.getIfNotNull(bid, AdnuntiusBid::getCurrency);
}

private static BidderBid makeBid(AdnuntiusAdsUnit adsUnit, String currency) {
private static BidderBid makeBid(AdnuntiusAdsUnit adsUnit, String impId, String currency) {
final AdnuntiusAd ad = adsUnit.getAds().get(0);
final String adId = ad.getAdId();
final Bid bid = Bid.builder()
.id(adId)
.impid(extractImpId(adsUnit))
.impid(impId)
.w(parseMeasure(ad.getCreativeWidth()))
.h(parseMeasure(ad.getCreativeHeight()))
.adid(adId)
Expand All @@ -243,15 +254,6 @@ private static BidderBid makeBid(AdnuntiusAdsUnit adsUnit, String currency) {
return BidderBid.of(bid, BidType.banner, currency);
}

private static String extractImpId(AdnuntiusAdsUnit adsUnit) {
final String targetId = adsUnit.getTargetId();
final String auId = adsUnit.getAuId();

return ObjectUtils.allNotNull(targetId, auId) && targetId.startsWith(auId + TARGET_ID_DELIMITER)
? targetId.substring(auId.length() + TARGET_ID_DELIMITER.length())
: null;
}

private static Integer parseMeasure(String measure) {
try {
return Integer.valueOf(measure);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.prebid.server.bidder.adnuntius.model.util;

import lombok.Value;
import org.prebid.server.bidder.adnuntius.model.response.AdnuntiusAdsUnit;

@Value(staticConstructor = "of")
public class AdsUnitWithImpId {

AdnuntiusAdsUnit adsUnit;

String impId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void makeHttpRequestsShouldReturnErrorWhenSomeImpBannerIsAbsent() {
// then
assertThat(result.getValue()).hasSize(0);
assertThat(result.getErrors()).extracting(BidderError::getMessage)
.containsExactly("Fail on Imp.Id=null: Adnuntius supports only Banner");
.containsExactly("Fail on Imp.Id=test: Adnuntius supports only Banner");
}

@Test
Expand Down Expand Up @@ -115,8 +115,9 @@ public void makeHttpRequestsShouldReturnRequestsWithAdUnitsSeparatedByImpExtNetw
@Test
public void makeHttpRequestsShouldReturnRequestsWithCorrectAdUnits() {
// given
final BidRequest bidRequest = givenBidRequest(givenImp(identity()),
givenImp(ExtImpAdnuntius.of("auId", null), identity()),
final BidRequest bidRequest = givenBidRequest(
givenImp(imp -> imp.id(null)),
givenImp(ExtImpAdnuntius.of("auId", null), imp -> imp.id(null)),
givenImp(ExtImpAdnuntius.of("auId", null), imp -> imp.id("impId")));

// when
Expand Down Expand Up @@ -289,9 +290,10 @@ public void makeBidsShouldReturnEmptyListIfResponseAdsUnitsIsEmpty() throws Json
public void makeBidsShouldSkipInvalidAdsUnits() throws JsonProcessingException {
// given
final HttpCall<AdnuntiusRequest> httpCall = givenHttpCall(givenAdsUnit());
final BidRequest bidRequest = givenBidRequest(givenImp(identity()));

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

// then
assertThat(result.getValue()).isEmpty();
Expand All @@ -307,8 +309,10 @@ public void makeBidsShouldUseCurrencyOfFirstBidOfLastAdsUnit() throws JsonProces
givenAdsUnit(givenAd(ad -> ad.bid(AdnuntiusBid.of(null, "2.1"))),
givenAd(ad -> ad.bid(AdnuntiusBid.of(null, "2.2")))));

final BidRequest bidRequest = givenBidRequest(givenImp(identity()), givenImp(identity()));

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

// then
assertThat(result.getValue()).extracting(BidderBid::getBidCurrency)
Expand All @@ -323,8 +327,10 @@ public void makeBidsShouldReturnErrorIfCreativeHeightOfSomeAdIsAbsent() throws J
givenAdsUnit(givenAd(ad -> ad.bid(AdnuntiusBid.of(null, "CUR")))),
givenAdsUnit(givenAd(ad -> ad.creativeHeight(null))));

final BidRequest bidRequest = givenBidRequest(givenImp(identity()), givenImp(identity()));

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

// then
assertThat(result.getValue()).isEmpty();
Expand All @@ -339,8 +345,10 @@ public void makeBidsShouldReturnErrorIfCreativeWidthtOfSomeAdIsAbsent() throws J
givenAdsUnit(givenAd(ad -> ad.bid(AdnuntiusBid.of(null, "CUR")))),
givenAdsUnit(givenAd(ad -> ad.creativeWidth(null))));

final BidRequest bidRequest = givenBidRequest(givenImp(identity()), givenImp(identity()));

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

// then
assertThat(result.getValue()).isEmpty();
Expand All @@ -359,8 +367,10 @@ public void makeBidsShouldReturnCorrectSeatBids() throws JsonProcessingException
.destinationUrls(Map.of("key1", "https://www.domain1.com/uri",
"key2", "http://www.domain2.dt/uri")))));

final BidRequest bidRequest = givenBidRequest(givenImp(imp -> imp.id("impId")));

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

// then
assertThat(result.getValue()).hasSize(1).allSatisfy(bidderBid -> {
Expand All @@ -383,6 +393,24 @@ public void makeBidsShouldReturnCorrectSeatBids() throws JsonProcessingException
assertThat(result.getErrors()).isEmpty();
}

@Test
public void makeBidsShouldReturnErrorWhenAdsUnitsCountGreaterThanImpsCount() throws JsonProcessingException {
// given
final HttpCall<AdnuntiusRequest> httpCall = givenHttpCall(
givenAdsUnit(givenAd(identity())),
givenAdsUnit(givenAd(identity())));

final BidRequest bidRequest = givenBidRequest(givenImp(identity()));

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

// then
assertThat(result.getValue()).isEmpty();
assertThat(result.getErrors()).extracting(BidderError::getMessage)
.containsExactly("Impressions count is less then ads units count.");
}

private BidRequest givenBidRequest(UnaryOperator<BidRequest.BidRequestBuilder> bidRequestCustomizer, Imp... imps) {
return bidRequestCustomizer.apply(BidRequest.builder()).imp(List.of(imps)).build();
}
Expand All @@ -394,7 +422,7 @@ private BidRequest givenBidRequest(Imp... imps) {
private Imp givenImp(ExtImpAdnuntius extImpAdnuntius, UnaryOperator<Imp.ImpBuilder> impCustomizer) {
final Banner banner = Banner.builder().build();
final ObjectNode ext = mapper.valueToTree(ExtPrebid.of(null, extImpAdnuntius));
return impCustomizer.apply(Imp.builder().banner(banner).ext(ext)).build();
return impCustomizer.apply(Imp.builder().id("test").banner(banner).ext(ext)).build();
}

private Imp givenImp(UnaryOperator<Imp.ImpBuilder> impCustomizer) {
Expand Down

0 comments on commit 641912e

Please sign in to comment.