From 2fa1a34b31268825dfc624df846448d058476dff Mon Sep 17 00:00:00 2001 From: serhiinahornyi Date: Wed, 31 Jan 2024 15:08:56 +0200 Subject: [PATCH] Rubicon: Adapter simplifications --- .../server/bidder/rubicon/RubiconBidder.java | 205 ++++---- .../proto/request/RubiconVideoExt.java | 2 - src/main/resources/bidder-config/rubicon.yaml | 11 +- .../bidder/rubicon/RubiconBidderTest.java | 445 ++++++------------ .../it/deals/test-rubicon-bid-request-1.json | 111 +++++ .../it/deals/test-rubicon-bid-request-2.json | 96 ++++ .../it/deals/test-rubicon-bid-request-3.json | 111 +++++ .../it/deals/test-rubicon-bid-request-4.json | 96 ++++ .../it/deals/test-rubicon-bid-request-5.json | 110 +++++ .../reject/test-rubicon-bid-request-1.json | 5 - .../test-rubicon-bid-request-1.json | 5 - .../magnite/test-magnite-bid-request.json | 5 - .../rubicon/test-rubicon-bid-request.json | 5 - 13 files changed, 742 insertions(+), 465 deletions(-) create mode 100644 src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-1.json create mode 100644 src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-2.json create mode 100644 src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-3.json create mode 100644 src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-4.json create mode 100644 src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-5.json diff --git a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java index 7943b3b04b2..5622d33417e 100644 --- a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java +++ b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java @@ -68,7 +68,6 @@ import org.prebid.server.bidder.rubicon.proto.request.RubiconUserExt; import org.prebid.server.bidder.rubicon.proto.request.RubiconUserExtRp; import org.prebid.server.bidder.rubicon.proto.request.RubiconVideoExt; -import org.prebid.server.bidder.rubicon.proto.request.RubiconVideoExtRp; import org.prebid.server.bidder.rubicon.proto.response.RubiconBid; import org.prebid.server.bidder.rubicon.proto.response.RubiconBidResponse; import org.prebid.server.bidder.rubicon.proto.response.RubiconSeatBid; @@ -79,14 +78,12 @@ import org.prebid.server.floors.model.PriceFloorRules; import org.prebid.server.json.DecodeException; import org.prebid.server.json.JacksonMapper; -import org.prebid.server.log.ConditionalLogger; import org.prebid.server.proto.openrtb.ext.ExtPrebid; import org.prebid.server.proto.openrtb.ext.FlexibleExtension; import org.prebid.server.proto.openrtb.ext.request.ExtApp; import org.prebid.server.proto.openrtb.ext.request.ExtDeal; import org.prebid.server.proto.openrtb.ext.request.ExtDealLine; import org.prebid.server.proto.openrtb.ext.request.ExtDevice; -import org.prebid.server.proto.openrtb.ext.request.ExtImpContext; import org.prebid.server.proto.openrtb.ext.request.ExtImpContextDataAdserver; import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebidFloors; @@ -133,8 +130,6 @@ public class RubiconBidder implements Bidder { private static final Logger logger = LoggerFactory.getLogger(RubiconBidder.class); - private static final ConditionalLogger MISSING_VIDEO_SIZE_LOGGER = - new ConditionalLogger("missing_video_size", logger); private static final String TK_XINT_QUERY_PARAMETER = "tk_xint"; private static final String PREBID_SERVER_USER_AGENT = "prebid-server/1.0"; @@ -143,12 +138,6 @@ public class RubiconBidder implements Bidder { private static final String FPD_GPID_FIELD = "gpid"; private static final String FPD_SKADN_FIELD = "skadn"; - private static final String FPD_SECTIONCAT_FIELD = "sectioncat"; - private static final String FPD_PAGECAT_FIELD = "pagecat"; - private static final String FPD_PAGE_FIELD = "page"; - private static final String FPD_REF_FIELD = "ref"; - private static final String FPD_SEARCH_FIELD = "search"; - private static final String FPD_CONTEXT_FIELD = "context"; private static final String FPD_DATA_FIELD = "data"; private static final String FPD_DATA_PBADSLOT_FIELD = "pbadslot"; private static final String FPD_ADSERVER_FIELD = "adserver"; @@ -159,13 +148,14 @@ public class RubiconBidder implements Bidder { private static final String PREBID_EXT = "prebid"; private static final String PPUID_STYPE = "ppuid"; - private static final String OTHER_STYPE = "other"; private static final String SHA256EMAIL_STYPE = "sha256email"; private static final String DMP_STYPE = "dmp"; + private static final String XAPI_CURRENCY = "USD"; private static final Set USER_SEGTAXES = Set.of(4); private static final Set SITE_SEGTAXES = Set.of(1, 2, 5, 6); + private static final String SEGTAX_BLAH_ATTRIBUTE = "segtaxBLAH"; private static final Set STYPE_TO_REMOVE = new HashSet<>(Arrays.asList(PPUID_STYPE, SHA256EMAIL_STYPE, DMP_STYPE)); @@ -176,6 +166,7 @@ public class RubiconBidder implements Bidder { new TypeReference<>() { }; private static final boolean DEFAULT_MULTIFORMAT_VALUE = false; + private static final int SEGTAX_BLAH_MAX_SIZE = 100; private final String endpointUrl; private final Set supportedVendors; @@ -663,7 +654,6 @@ private RubiconImpExt makeImpExt(Imp imp, String ipfResolvedCurrency, PriceFloorResult priceFloorResult) { - final ExtImpContext context = extImpContext(imp); final RubiconImpExtPrebid rubiconImpExtPrebid = priceFloorResult != null ? makeRubiconExtPrebid(priceFloorResult, ipfResolvedCurrency, imp, bidRequest) : null; @@ -674,7 +664,7 @@ private RubiconImpExt makeImpExt(Imp imp, final RubiconImpExtRp rubiconImpExtRp = RubiconImpExtRp.of( rubiconImpExt.getZoneId(), - makeTarget(imp, rubiconImpExt, site, app, context), + makeTarget(imp, rubiconImpExt, site, app), RubiconImpExtRpTrack.of("", ""), rubiconImpExtRpRtb); @@ -688,26 +678,14 @@ private RubiconImpExt makeImpExt(Imp imp, .build(); } - private ExtImpContext extImpContext(Imp imp) { - final JsonNode context = imp.getExt().get(FPD_CONTEXT_FIELD); - if (context == null || context.isNull()) { - return null; - } - try { - return mapper.mapper().convertValue(context, ExtImpContext.class); - } catch (IllegalArgumentException e) { - throw new PreBidException(e.getMessage(), e); - } - } - - private JsonNode makeTarget(Imp imp, ExtImpRubicon rubiconImpExt, Site site, App app, ExtImpContext context) { + private JsonNode makeTarget(Imp imp, ExtImpRubicon rubiconImpExt, Site site, App app) { final ObjectNode result = mapper.mapper().createObjectNode(); populateFirstPartyDataAttributes(rubiconImpExt.getInventory(), result); mergeFirstPartyDataFromSite(site, result); mergeFirstPartyDataFromApp(app, result); - mergeFirstPartyDataFromImp(imp, rubiconImpExt, context, result); + mergeFirstPartyDataFromImp(imp, rubiconImpExt, result); return result.size() > 0 ? result : null; } @@ -742,17 +720,6 @@ private void mergeFirstPartyDataFromSite(Site site, ObjectNode result) { if (siteExt != null) { populateFirstPartyDataAttributes(siteExt.getData(), result); } - - // merge OPENRTB.site.sectioncat to every impression XAPI.imp[].ext.rp.target.sectioncat - mergeCollectionAttributeIntoArray(result, site, Site::getSectioncat, FPD_SECTIONCAT_FIELD); - // merge OPENRTB.site.pagecat to every impression XAPI.imp[].ext.rp.target.pagecat - mergeCollectionAttributeIntoArray(result, site, Site::getPagecat, FPD_PAGECAT_FIELD); - // merge OPENRTB.site.page to every impression XAPI.imp[].ext.rp.target.page - mergeStringAttributeIntoArray(result, site, Site::getPage, FPD_PAGE_FIELD); - // merge OPENRTB.site.ref to every impression XAPI.imp[].ext.rp.target.ref - mergeStringAttributeIntoArray(result, site, Site::getRef, FPD_REF_FIELD); - // merge OPENRTB.site.search to every impression XAPI.imp[].ext.rp.target.search - mergeStringAttributeIntoArray(result, site, Site::getSearch, FPD_SEARCH_FIELD); } private void mergeFirstPartyDataFromApp(App app, ObjectNode result) { @@ -761,72 +728,41 @@ private void mergeFirstPartyDataFromApp(App app, ObjectNode result) { if (appExt != null) { populateFirstPartyDataAttributes(appExt.getData(), result); } - - // merge OPENRTB.app.sectioncat to every impression XAPI.imp[].ext.rp.target.sectioncat - mergeCollectionAttributeIntoArray(result, app, App::getSectioncat, FPD_SECTIONCAT_FIELD); - // merge OPENRTB.app.pagecat to every impression XAPI.imp[].ext.rp.target.pagecat - mergeCollectionAttributeIntoArray(result, app, App::getPagecat, FPD_PAGECAT_FIELD); } private void mergeFirstPartyDataFromImp(Imp imp, ExtImpRubicon rubiconImpExt, - ExtImpContext context, ObjectNode result) { - - mergeFirstPartyDataFromData(imp, context, result); - mergeFirstPartyDataKeywords(imp, context, result); + mergeFirstPartyDataKeywords(imp, result); + mergeFirstPartyDataFromData(imp, result); // merge OPENRTB.imp[].ext.rubicon.keywords to XAPI.imp[].ext.rp.target.keywords mergeCollectionAttributeIntoArray(result, rubiconImpExt, ExtImpRubicon::getKeywords, FPD_KEYWORDS_FIELD); - // merge OPENRTB.imp[].ext.context.search to XAPI.imp[].ext.rp.target.search - mergeStringAttributeIntoArray( - result, - context, - extContext -> getTextValueFromNode(extContext.getProperty(FPD_SEARCH_FIELD)), - FPD_SEARCH_FIELD); - // merge OPENRTB.imp[].ext.data.search to XAPI.imp[].ext.rp.target.search - mergeStringAttributeIntoArray( - result, - imp.getExt().get(FPD_DATA_FIELD), - node -> getTextValueFromNodeByPath(node, FPD_SEARCH_FIELD), - FPD_SEARCH_FIELD); - } - - private void mergeFirstPartyDataFromData(Imp imp, ExtImpContext context, ObjectNode result) { - final ObjectNode contextDataNode = toObjectNode( - ObjectUtil.getIfNotNull(context, ExtImpContext::getData)); - // merge OPENRTB.imp[].ext.context.data.* to XAPI.imp[].ext.rp.target.* - populateFirstPartyDataAttributes(contextDataNode, result); + } + private void mergeFirstPartyDataFromData(Imp imp, ObjectNode result) { final ObjectNode dataNode = toObjectNode(imp.getExt().get(FPD_DATA_FIELD)); // merge OPENRTB.imp[].ext.data.* to XAPI.imp[].ext.rp.target.* populateFirstPartyDataAttributes(dataNode, result); // override XAPI.imp[].ext.rp.target.* with OPENRTB.imp[].ext.data.* - overrideFirstPartyDataAttributes(contextDataNode, dataNode, result); + overrideFirstPartyDataAttributes(dataNode, result); } - private void overrideFirstPartyDataAttributes(ObjectNode contextDataNode, ObjectNode dataNode, ObjectNode result) { + private void overrideFirstPartyDataAttributes(ObjectNode dataNode, ObjectNode result) { final JsonNode pbadslotNode = dataNode.get(FPD_DATA_PBADSLOT_FIELD); if (pbadslotNode != null && pbadslotNode.isTextual()) { // copy imp[].ext.data.pbadslot to XAPI.imp[].ext.rp.target.pbadslot result.set(FPD_DATA_PBADSLOT_FIELD, pbadslotNode); } else { // copy adserver.adslot value to XAPI field imp[].ext.rp.target.dfp_ad_unit_code - final String resolvedDfpAdUnitCode = getAdSlot(contextDataNode, dataNode); + final String resolvedDfpAdUnitCode = getAdSlotFromAdServer(dataNode); if (resolvedDfpAdUnitCode != null) { result.set(DFP_ADUNIT_CODE_FIELD, TextNode.valueOf(resolvedDfpAdUnitCode)); } } } - private void mergeFirstPartyDataKeywords(Imp imp, ExtImpContext context, ObjectNode result) { - // merge OPENRTB.imp[].ext.context.keywords to XAPI.imp[].ext.rp.target.keywords - final JsonNode keywordsNode = context != null ? context.getProperty("keywords") : null; - final String keywords = getTextValueFromNode(keywordsNode); - if (StringUtils.isNotBlank(keywords)) { - mergeIntoArray(result, FPD_KEYWORDS_FIELD, keywords.split(",")); - } - + private void mergeFirstPartyDataKeywords(Imp imp, ObjectNode result) { // merge OPENRTB.imp[].ext.data.keywords to XAPI.imp[].ext.rp.target.keywords final String dataKeywords = getTextValueFromNodeByPath(imp.getExt().get(FPD_DATA_FIELD), FPD_KEYWORDS_FIELD); if (StringUtils.isNotBlank(dataKeywords)) { @@ -976,19 +912,10 @@ private ObjectNode getSkadn(ObjectNode impExt) { return skadnNode != null && skadnNode.isObject() ? (ObjectNode) skadnNode : null; } - private String getAdSlot(Imp imp, ExtImpContext context) { - final ObjectNode contextDataNode = context != null ? context.getData() : null; + private String getAdSlot(Imp imp) { final ObjectNode dataNode = toObjectNode(imp.getExt().get(FPD_DATA_FIELD)); - return getAdSlot(contextDataNode, dataNode); - } - - private String getAdSlot(ObjectNode contextDataNode, ObjectNode dataNode) { - return ObjectUtils.firstNonNull( - // or imp[].ext.context.data.adserver.adslot - getAdSlotFromAdServer(contextDataNode), - // or imp[].ext.data.adserver.adslot - getAdSlotFromAdServer(dataNode)); + return getAdSlotFromAdServer(dataNode); } private String getAdSlotFromAdServer(JsonNode dataNode) { @@ -1039,54 +966,20 @@ private Video makeVideo(Imp imp, RubiconVideoParams rubiconVideoParams, String r final Integer skip = rubiconVideoParams != null ? rubiconVideoParams.getSkip() : null; final Integer skipDelay = rubiconVideoParams != null ? rubiconVideoParams.getSkipdelay() : null; - final Integer sizeId = rubiconVideoParams != null ? rubiconVideoParams.getSizeId() : null; - - final Integer resolvedSizeId = BidderUtil.isNullOrZero(sizeId) - ? resolveVideoSizeId(video.getPlacement(), imp.getInstl()) - : sizeId; - validateVideoSizeId(resolvedSizeId, referer, imp.getId()); final Integer rewarded = imp.getRwdd(); final String videoType = rewarded != null && rewarded == 1 ? "rewarded" : null; // optimization for empty ext params - if (skip == null && skipDelay == null && resolvedSizeId == null && videoType == null) { + if (skip == null && skipDelay == null && videoType == null) { return video; } return video.toBuilder() - .ext(mapper.mapper().valueToTree( - RubiconVideoExt.of(skip, skipDelay, RubiconVideoExtRp.of(resolvedSizeId), videoType))) + .ext(mapper.mapper().valueToTree(RubiconVideoExt.of(skip, skipDelay, videoType))) .build(); } - private static void validateVideoSizeId(Integer resolvedSizeId, String referer, String impId) { - // log only 1% of cases to monitor how often video impressions does not have size id - if (resolvedSizeId == null) { - MISSING_VIDEO_SIZE_LOGGER.warn( - "RP adapter: video request with no size_id. Referrer URL = %s, impId = %s" - .formatted(referer, impId), - 0.01d); - } - } - - private static Integer resolveVideoSizeId(Integer placement, Integer instl) { - if (placement != null) { - if (placement == 1) { - return 201; - } - if (placement == 3) { - return 203; - } - } - - if (instl != null && instl == 1) { - return 202; - } - - return null; - } - private Banner makeBanner(Imp imp) { final Banner banner = imp.getBanner(); final Integer width = banner.getW(); @@ -1187,6 +1080,7 @@ private User makeUser(User user, ExtImpRubicon rubiconImpExt) { final ExtUser userExt = ExtUser.builder() .eids(resolvedUserEids) + .fcapIds(extUser != null ? extUser.getFcapIds() : null) .build(); final RubiconUserExt rubiconUserExt = RubiconUserExt.builder() @@ -1327,6 +1221,7 @@ private JsonNode rubiconUserExtRpTarget(ObjectNode visitor, User user) { mergeFirstPartyDataFromUser(user.getExt(), result); enrichWithIabAttribute(result, user.getData(), USER_SEGTAXES); + enrichWithSegtaxBlahAttribute(result, user.getData(), USER_SEGTAXES); } return !result.isEmpty() ? result : null; @@ -1367,6 +1262,63 @@ private static void enrichWithIabAttribute(ObjectNode target, List data, S } } + private static void enrichWithSegtaxBlahAttribute(ObjectNode target, List data, Set segtaxValues) { + final List> validDataSegments = getValidDataSegments( + CollectionUtils.emptyIfNull(data).stream() + .filter(Objects::nonNull) + .filter(dataRecord -> !containsSegtaxValue(dataRecord.getExt(), segtaxValues)) + .map(Data::getSegment) + .filter(CollectionUtils::isNotEmpty) + .collect(Collectors.toCollection(ArrayList::new))); + + if (CollectionUtils.isEmpty(validDataSegments)) { + return; + } + + final List values = resolveSegtaxBlahValues(validDataSegments); + final ArrayNode segtaxBlah = target.putArray(SEGTAX_BLAH_ATTRIBUTE); + values.forEach(segtaxBlah::add); + } + + private static List> getValidDataSegments(List> dataSegments) { + return dataSegments.stream() + .map(RubiconBidder::getValidOnlySegments) + .filter(CollectionUtils::isNotEmpty) + .collect(Collectors.toCollection(ArrayList::new)); + } + + private static List getValidOnlySegments(List segments) { + return segments.stream() + .filter(segment -> StringUtils.isNotBlank(segment.getId())) + .collect(Collectors.toCollection(ArrayList::new)); + } + + private static List resolveSegtaxBlahValues(final List> segments) { + final List values = new ArrayList<>(); + for (int i = 0; i < SEGTAX_BLAH_MAX_SIZE; i++) { + final int segmentsIndex = i % segments.size(); + final List currentSegments = segments.get(segmentsIndex); + values.add(getAndRemoveLastSegment(currentSegments).getId()); + + if (CollectionUtils.isEmpty(currentSegments)) { + segments.remove(segmentsIndex); + if (CollectionUtils.isEmpty(segments)) { + break; + } + } + } + + return values; + } + + private static Segment getAndRemoveLastSegment(List list) { + final int lastElementIndex = list.size() - 1; + final Segment lastSegment = list.get(lastElementIndex); + list.remove(lastElementIndex); + + return lastSegment; + } + private static boolean containsSegtaxValue(ObjectNode ext, Set segtaxValues) { final JsonNode taxonomyName = ext != null ? ext.get("segtax") : null; @@ -1443,6 +1395,7 @@ private ExtSite makeSiteExt(Site site, ExtImpRubicon rubiconImpExt) { if (CollectionUtils.isNotEmpty(siteContentData)) { target = existingRubiconSiteExtRpTargetOrEmptyNode(extSite); enrichWithIabAttribute(target, siteContentData, SITE_SEGTAXES); + enrichWithSegtaxBlahAttribute(target, siteContentData, SITE_SEGTAXES); } return mapper.fillExtension( @@ -1554,7 +1507,7 @@ private BidRequest createLineItemBidRequest(ExtDealLine lineItem, BidRequest bid final Imp dealsImp = imp.toBuilder() .banner(modifyBanner(imp.getBanner(), lineItem.getSizes())) .ext(modifyRubiconImpExt(imp.getExt(), bidRequest.getExt(), lineItem.getExtLineItemId(), - getAdSlot(imp, extImpContext(imp)))) + getAdSlot(imp))) .build(); return bidRequest.toBuilder() diff --git a/src/main/java/org/prebid/server/bidder/rubicon/proto/request/RubiconVideoExt.java b/src/main/java/org/prebid/server/bidder/rubicon/proto/request/RubiconVideoExt.java index 1d545488b4e..9f32e9124cf 100644 --- a/src/main/java/org/prebid/server/bidder/rubicon/proto/request/RubiconVideoExt.java +++ b/src/main/java/org/prebid/server/bidder/rubicon/proto/request/RubiconVideoExt.java @@ -11,7 +11,5 @@ public class RubiconVideoExt { Integer skipdelay; - RubiconVideoExtRp rp; - String videotype; } diff --git a/src/main/resources/bidder-config/rubicon.yaml b/src/main/resources/bidder-config/rubicon.yaml index a7a4fcc1eea..d2b2f741dff 100644 --- a/src/main/resources/bidder-config/rubicon.yaml +++ b/src/main/resources/bidder-config/rubicon.yaml @@ -1,16 +1,9 @@ adapters: rubicon: ortb-version: "2.6" - # Contact global-support@magnite.com to ask about enabling a connection to the Magnite (formerly Rubicon) exchange. - # We have the following regional endpoint domains: exapi-us-east, exapi-us-west, exapi-apac, exapi-eu - # Please deploy this config in each of your datacenters with the appropriate regional subdomain - endpoint: "https://REGION.rubiconproject.com/a/api/exchange" - endpoint-compression: gzip - geoscope: - - global + endpoint: http://exapi-us-east.rubiconproject.com/a/api/exchange.json aliases: - magnite: - enabled: false + magnite: ~ meta-info: maintainer-email: header-bidding@rubiconproject.com app-media-types: diff --git a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java index 8bd9cdbcaf1..cc1245b0318 100644 --- a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java @@ -69,7 +69,6 @@ import org.prebid.server.bidder.rubicon.proto.request.RubiconUserExt; import org.prebid.server.bidder.rubicon.proto.request.RubiconUserExtRp; import org.prebid.server.bidder.rubicon.proto.request.RubiconVideoExt; -import org.prebid.server.bidder.rubicon.proto.request.RubiconVideoExtRp; import org.prebid.server.bidder.rubicon.proto.response.RubiconBid; import org.prebid.server.bidder.rubicon.proto.response.RubiconBidResponse; import org.prebid.server.bidder.rubicon.proto.response.RubiconSeatBid; @@ -117,6 +116,7 @@ import java.util.Set; import java.util.function.Function; import java.util.function.UnaryOperator; +import java.util.stream.IntStream; import static java.math.BigDecimal.ONE; import static java.math.BigDecimal.TEN; @@ -808,75 +808,6 @@ public void makeHttpRequestsShouldIgnoreBidRequestIfCurrencyServiceThrowsAnExcep + " for imp `impId` with a reason: failed", BidderError.Type.bad_input)); } - @Test - public void shouldSetSizeIdTo201IfPlacementIs1AndSizeIdIsNotPresent() { - // given - final BidRequest bidRequest = givenBidRequest( - builder -> builder.instl(1).video(Video.builder().placement(1).build()), - builder -> builder.video(RubiconVideoParams.builder().sizeId(null).build())); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1).doesNotContainNull() - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getVideo).doesNotContainNull() - .extracting(Video::getExt).doesNotContainNull() - .extracting(ext -> mapper.treeToValue(ext, RubiconVideoExt.class)) - .extracting(RubiconVideoExt::getRp) - .extracting(RubiconVideoExtRp::getSizeId) - .containsOnly(201); - } - - @Test - public void shouldSetSizeIdTo203IfPlacementIs3AndSizeIdIsNotPresent() { - // given - final BidRequest bidRequest = givenBidRequest( - builder -> builder.instl(1).video(Video.builder().placement(3).build()), - builder -> builder.video(RubiconVideoParams.builder().sizeId(null).build())); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1).doesNotContainNull() - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getVideo).doesNotContainNull() - .extracting(Video::getExt).doesNotContainNull() - .extracting(ext -> mapper.treeToValue(ext, RubiconVideoExt.class)) - .extracting(RubiconVideoExt::getRp) - .extracting(RubiconVideoExtRp::getSizeId) - .containsOnly(203); - } - - @Test - public void shouldSetSizeIdTo202UsingInstlFlagIfPlacementAndSizeIdAreNotPresent() { - // given - final BidRequest bidRequest = givenBidRequest( - builder -> builder.instl(1).video(Video.builder().placement(null).build()), - builder -> builder.video(RubiconVideoParams.builder().sizeId(null).build())); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1).doesNotContainNull() - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getVideo).doesNotContainNull() - .extracting(Video::getExt).doesNotContainNull() - .extracting(ext -> mapper.treeToValue(ext, RubiconVideoExt.class)) - .extracting(RubiconVideoExt::getRp) - .extracting(RubiconVideoExtRp::getSizeId) - .containsOnly(202); - } - @Test public void makeHttpRequestsShouldFillVideoExt() { // given @@ -895,7 +826,7 @@ public void makeHttpRequestsShouldFillVideoExt() { .extracting(Imp::getVideo).doesNotContainNull() .extracting(Video::getExt).doesNotContainNull() .extracting(ext -> mapper.treeToValue(ext, RubiconVideoExt.class)) - .containsOnly(RubiconVideoExt.of(5, 10, RubiconVideoExtRp.of(14), null)); + .containsOnly(RubiconVideoExt.of(5, 10, null)); } @Test @@ -923,7 +854,8 @@ public void makeHttpRequestsShouldTransferRewardedVideoFlagIntoRewardedVideoObje .extracting(Imp::getVideo).doesNotContainNull() .extracting(Video::getExt).doesNotContainNull() .extracting(ex -> mapper.treeToValue(ex, RubiconVideoExt.class)) - .containsOnly(RubiconVideoExt.of(5, 10, RubiconVideoExtRp.of(14), "rewarded")); + .extracting(RubiconVideoExt::getVideotype) + .containsOnly("rewarded"); } @Test @@ -950,7 +882,8 @@ public void makeHttpRequestsShouldIgnoreRewardedVideoLogic() { .extracting(Imp::getVideo).doesNotContainNull() .extracting(Video::getExt).doesNotContainNull() .extracting(ex -> mapper.treeToValue(ex, RubiconVideoExt.class)) - .containsOnly(RubiconVideoExt.of(5, 10, RubiconVideoExtRp.of(14), null)); + .extracting(RubiconVideoExt::getVideotype) + .containsOnlyNulls(); } @Test @@ -977,7 +910,8 @@ public void makeHttpRequestsShouldIgnoreRewardedVideoLogicIfRewardedInventoryIsN .extracting(Imp::getVideo).doesNotContainNull() .extracting(Video::getExt).doesNotContainNull() .extracting(ex -> mapper.treeToValue(ex, RubiconVideoExt.class)) - .containsOnly(RubiconVideoExt.of(5, 10, RubiconVideoExtRp.of(14), null)); + .extracting(RubiconVideoExt::getVideotype) + .containsOnlyNulls(); } @Test @@ -1025,7 +959,7 @@ public void makeHttpRequestsShouldIgnoreRewardedVideoFlag() { .extracting(Imp::getVideo).doesNotContainNull() .extracting(Video::getExt).doesNotContainNull() .extracting(ex -> mapper.treeToValue(ex, RubiconVideoExt.class)) - .containsOnly(RubiconVideoExt.of(5, 10, RubiconVideoExtRp.of(14), null)); + .containsOnly(RubiconVideoExt.of(5, 10, null)); } @Test @@ -1055,6 +989,70 @@ public void makeHttpRequestsShouldFillUserExtIfUserAndVisitorPresent() { .build()); } + @Test + public void makeHttpRequestsShouldFillUserExtRpWithSegtaxBlahWithNoMoreThanHundredAttributes() { + // given + final List segments = IntStream.range(0, 150) + .mapToObj(index -> givenDataWithSegmentEntry(3, "SegmentId_" + index)) + .toList(); + + final BidRequest bidRequest = givenBidRequest( + builder -> builder.user(User.builder().data(segments).build()), + builder -> builder.video(Video.builder().build()), + identity()); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedTarget = mapper.createObjectNode(); + final ArrayNode expectedIabAttribute = expectedTarget.putArray("iab"); + expectedIabAttribute.add("segmentId"); + + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1).doesNotContainNull() + .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) + .extracting(BidRequest::getUser).doesNotContainNull() + .extracting(User::getExt) + .extracting(userExt -> userExt.getProperty("rp")) + .extracting(rp -> rp.get("target")) + .extracting(target -> target.get("segtaxBLAH")) + .extracting(JsonNode::size) + .containsExactly(100); + } + + @Test + public void makeHttpRequestsShouldFillUserExtRpWithSegtaxBlahWithSegtaxesFromEachData() { + // given + final List dataWithSegments = asList(givenTestDataWithSegmentEntries(3), + givenDataWithSegmentEntry(3, "Included_SegmentId_1"), + givenDataWithSegmentEntry(3, "Included_SegmentId_2")); + + final BidRequest bidRequest = givenBidRequest( + builder -> builder.user(User.builder().data(dataWithSegments).build()), + builder -> builder.video(Video.builder().build()), + identity()); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedTarget = mapper.createObjectNode(); + final ArrayNode expectedIabAttribute = expectedTarget.putArray("iab"); + expectedIabAttribute.add("segmentId"); + + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1).doesNotContainNull() + .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) + .extracting(BidRequest::getUser).doesNotContainNull() + .extracting(User::getExt) + .extracting(userExt -> userExt.getProperty("rp")) + .extracting(rp -> rp.get("target")) + .extracting(target -> target.get("segtaxBLAH")) + .flatExtracting(blah -> mapper.convertValue(blah, List.class)) + .contains("Included_SegmentId_1", "Included_SegmentId_2"); + } + @Test public void makeHttpRequestsShouldFillUserExtRpWithIabAttributeIfSegtaxEqualsFour() { // given @@ -1109,7 +1107,7 @@ public void makeHttpRequestsShouldRemoveUserDataObject() { } @Test - public void makeHttpRequestsShouldFillUserExtRpWithIabAttributeOnlyIfSegtaxIsEqualFour() { + public void makeHttpRequestsShouldFillUserExtRpWithIabAttributeAndSegtaxBlahIfSegtaxIsEqualFour() { // given final BidRequest bidRequest = givenBidRequest( builder -> builder.user(User.builder() @@ -1127,6 +1125,8 @@ public void makeHttpRequestsShouldFillUserExtRpWithIabAttributeOnlyIfSegtaxIsEqu final ObjectNode expectedTarget = mapper.createObjectNode(); final ArrayNode expectedIabAttribute = expectedTarget.putArray("iab"); expectedIabAttribute.add("segmentId"); + final ArrayNode expectedSegtaxBLAHAttribute = expectedTarget.putArray("segtaxBLAH"); + expectedSegtaxBLAHAttribute.add("secondSegmentId"); assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()).hasSize(1).doesNotContainNull() @@ -1141,7 +1141,7 @@ public void makeHttpRequestsShouldFillUserExtRpWithIabAttributeOnlyIfSegtaxIsEqu } @Test - public void makeHttpRequestsShouldFillSiteExtRpWithIabAttributeIfSegtaxEqualsOneOrTwoOrFiveOrSix() { + public void makeHttpRequestsShouldFillSiteExtRpWithSegtaxBlahAndIabAttributeIfSegtaxEqualsOneOrTwoOrFiveOrSix() { // given final BidRequest bidRequest = givenBidRequest( builder -> builder.site(Site.builder() @@ -1167,6 +1167,8 @@ public void makeHttpRequestsShouldFillSiteExtRpWithIabAttributeIfSegtaxEqualsOne expectedIabAttribute.add("secondSegmentId"); expectedIabAttribute.add("fifthSegmentId"); expectedIabAttribute.add("sixthSegmentId"); + final ArrayNode expectedSegtaxBLAHAttribute = expectedTarget.putArray("segtaxBLAH"); + expectedSegtaxBLAHAttribute.add("thirdSegmentId"); assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()).hasSize(1).doesNotContainNull() @@ -1178,6 +1180,38 @@ public void makeHttpRequestsShouldFillSiteExtRpWithIabAttributeIfSegtaxEqualsOne .containsExactly(expectedTarget); } + @Test + public void makeHttpRequestsShouldFillSiteExtRpWithSegtaxBlahWithNoMoreThanHundredEntries() { + // given + final List segments = IntStream.range(0, 150) + .mapToObj(index -> givenDataWithSegmentEntry(3, "SegmentId_" + index)) + .toList(); + + final BidRequest bidRequest = givenBidRequest( + builder -> builder.site(Site.builder() + .content(Content.builder() + .data(segments) + .build()) + .build()), + builder -> builder.video(Video.builder().build()), + identity()); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1).doesNotContainNull() + .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) + .extracting(BidRequest::getSite).doesNotContainNull() + .extracting(Site::getExt) + .extracting(ext -> ext.getProperty("rp")) + .extracting(rp -> rp.get("target")) + .extracting(rp -> rp.get("segtaxBLAH")) + .extracting(JsonNode::size) + .containsExactly(100); + } + @Test public void makeHttpRequestsShouldRemoveSiteContentDataObject() { // given @@ -1208,7 +1242,7 @@ public void makeHttpRequestsShouldRemoveSiteContentDataObject() { } @Test - public void makeHttpRequestsShouldIgnoreNotIntSegtaxProperty() { + public void makeHttpRequestsShouldSetSegtaxBlahProperty() { // given final ObjectNode userNode = mapper.createObjectNode(); userNode.put("segtax", "3"); @@ -1224,12 +1258,17 @@ public void makeHttpRequestsShouldIgnoreNotIntSegtaxProperty() { final Result>> result = target.makeHttpRequests(bidRequest); // then + final ObjectNode expectedTarget = mapper.createObjectNode(); + final ArrayNode expectedSegtaxBLAHAttribute = expectedTarget.putArray("segtaxBLAH"); + expectedSegtaxBLAHAttribute.add("segmentId"); assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()).hasSize(1).doesNotContainNull() .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) .extracting(BidRequest::getUser).doesNotContainNull() .extracting(User::getExt) - .containsNull(); + .extracting(ext -> ext.getProperty("rp")) + .extracting(rp -> rp.get("target")) + .containsExactly(expectedTarget); } @Test @@ -2371,7 +2410,7 @@ public void makeHttpRequestsShouldCreateRequestPerImp() { } @Test - public void makeHttpRequestsShouldCopyAndModifyImpExtContextDataAndDataFieldsToRubiconImpExtRpTarget() { + public void makeHttpRequestsShouldCopyAndModifyDataFieldToRubiconImpExtRpTarget() { // given final BidRequest bidRequest = givenBidRequest( identity(), @@ -2398,7 +2437,6 @@ public void makeHttpRequestsShouldCopyAndModifyImpExtContextDataAndDataFieldsToR .extracting(RubiconImpExt::getRp) .extracting(RubiconImpExtRp::getTarget) .containsOnly(mapper.createObjectNode() - .set("property1", mapper.createArrayNode().add("value1")) .set("property2", mapper.createArrayNode().add("value2"))); } @@ -2423,66 +2461,6 @@ public void makeHttpRequestsShouldPassThroughImpExtGpid() { .containsExactly(TextNode.valueOf("gpidvalue")); } - @Test - public void makeHttpRequestsShouldNotCopyAdSlotFromAdServerWhenAdServerNameIsNotGam() { - // given - final BidRequest bidRequest = givenBidRequest( - identity(), - impBuilder -> impBuilder.video(Video.builder().build()), - identity()); - - bidRequest.getImp().get(0).getExt() - .set("context", mapper.createObjectNode() - .set("data", mapper.createObjectNode() - .put("property", "value") - .set("adserver", mapper.createObjectNode() - .put("name", "not-gam") - .put("adslot", "/test-adserver")))); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getExt) - .extracting(objectNode -> mapper.convertValue(objectNode, RubiconImpExt.class)) - .extracting(RubiconImpExt::getRp) - .extracting(RubiconImpExtRp::getTarget) - .containsOnly(mapper.createObjectNode() - .set("property", mapper.createArrayNode().add("value"))); - } - - @Test - public void makeHttpRequestsShouldNotCopyAndModifyImpExtContextDataAdslotToRubiconImpExtRpTargetDfpAdUnitCode() { - // given - final BidRequest bidRequest = givenBidRequest( - identity(), - impBuilder -> impBuilder.video(Video.builder().build()), - identity()); - - final ObjectNode impExt = bidRequest.getImp().get(0).getExt(); - final ObjectNode impExtContextDataNode = mapper.createObjectNode() - .set("adslot", mapper.createArrayNode().add("123")); - impExt.set("context", mapper.valueToTree(ExtImpContext.of(impExtContextDataNode))); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getExt) - .extracting(objectNode -> mapper.convertValue(objectNode, RubiconImpExt.class)) - .extracting(RubiconImpExt::getRp) - .extracting(RubiconImpExtRp::getTarget) - .containsOnly(mapper.createObjectNode().set("adslot", mapper.createArrayNode().add("123"))); - } - @Test public void makeHttpRequestsShouldCopySiteExtDataFieldsToRubiconImpExtRpTarget() { // given @@ -2536,13 +2514,11 @@ public void makeHttpRequestsShouldCopyAppExtDataFieldsToRubiconImpExtRpTarget() } @Test - public void makeHttpRequestsShouldCopySiteExtDataAndImpExtContextDataFieldsToRubiconImpExtRpTarget() + public void makeHttpRequestsShouldCopySiteExtDataFieldToRubiconImpExtRpTarget() throws IOException { // given final ObjectNode siteExtDataNode = mapper.createObjectNode() .set("site", mapper.createArrayNode().add("value1")); - final ObjectNode impExtContextDataNode = mapper.createObjectNode() - .set("imp_ext", mapper.createArrayNode().add("value2")); final BidRequest bidRequest = givenBidRequest( requestBuilder -> requestBuilder @@ -2550,9 +2526,6 @@ public void makeHttpRequestsShouldCopySiteExtDataAndImpExtContextDataFieldsToRub impBuilder -> impBuilder.video(Video.builder().build()), identity()); - final ObjectNode impExt = bidRequest.getImp().get(0).getExt(); - impExt.set("context", mapper.valueToTree(ExtImpContext.of(impExtContextDataNode))); - // when final Result>> result = target.makeHttpRequests(bidRequest); @@ -2565,11 +2538,11 @@ public void makeHttpRequestsShouldCopySiteExtDataAndImpExtContextDataFieldsToRub .extracting(objectNode -> mapper.convertValue(objectNode, RubiconImpExt.class)) .extracting(RubiconImpExt::getRp) .extracting(RubiconImpExtRp::getTarget) - .containsOnly(mapper.readTree("{\"imp_ext\":[\"value2\"],\"site\":[\"value1\"]}")); + .containsOnly(mapper.readTree("{\"site\":[\"value1\"]}")); } @Test - public void makeHttpRequestsShouldCopyAppExtDataAndImpExtContextDataFieldsToRubiconImpExtRpTarget() + public void makeHttpRequestsShouldCopyAppExtDataFieldToRubiconImpExtRpTarget() throws IOException { // given final ObjectNode appExtDataNode = mapper.createObjectNode() @@ -2598,11 +2571,11 @@ public void makeHttpRequestsShouldCopyAppExtDataAndImpExtContextDataFieldsToRubi .extracting(objectNode -> mapper.convertValue(objectNode, RubiconImpExt.class)) .extracting(RubiconImpExt::getRp) .extracting(RubiconImpExtRp::getTarget) - .containsOnly(mapper.readTree("{\"imp_ext\":[\"value2\"],\"app\":[\"value1\"]}")); + .containsOnly(mapper.readTree("{\"app\":[\"value1\"]}")); } @Test - public void makeHttpRequestsShouldMergeImpExtRubiconAndContextAndDataKeywordsToRubiconImpExtRpTargetKeywords() + public void makeHttpRequestsShouldMergeImpExtRubiconKeywordsToRubiconImpExtRpTargetKeywords() throws IOException { // given @@ -2612,9 +2585,6 @@ public void makeHttpRequestsShouldMergeImpExtRubiconAndContextAndDataKeywordsToR identity()); final ObjectNode impExt = bidRequest.getImp().get(0).getExt(); - final ExtImpContext extImpContext = ExtImpContext.of(null); - extImpContext.addProperty("keywords", new TextNode("imp,ext,context,keywords")); - impExt.set("context", mapper.valueToTree(extImpContext)); impExt.set("data", mapper.createObjectNode() .put("keywords", "imp,ext,data,keywords")); impExt.set( @@ -2636,12 +2606,11 @@ public void makeHttpRequestsShouldMergeImpExtRubiconAndContextAndDataKeywordsToR .extracting(RubiconImpExt::getRp) .extracting(RubiconImpExtRp::getTarget) .containsOnly(mapper.readTree("{\"keywords\":[" - + "\"imp,ext,data,keywords\"," + " \"imp\"," + " \"ext\"," - + " \"context\"," - + " \"keywords\"," + " \"data\"," + + " \"keywords\"," + + "\"imp,ext,data,keywords\"," + " \"rubicon\"" + "]}")); } @@ -2672,7 +2641,7 @@ public void makeHttpRequestsShouldCopyImpExtContextAndDataSearchToRubiconImpExtR .extracting(objectNode -> mapper.convertValue(objectNode, RubiconImpExt.class)) .extracting(RubiconImpExt::getRp) .extracting(RubiconImpExtRp::getTarget) - .containsOnly(mapper.readTree("{\"search\":[\"imp ext data search\", \"imp ext context search\"]}")); + .containsOnly(mapper.readTree("{\"search\":[\"imp ext data search\"]}")); } @Test @@ -2695,89 +2664,6 @@ public void makeHttpRequestsShouldCopyImpExtVideoLanguageToSiteContentLanguage() .containsOnly("ua"); } - @Test - public void makeHttpRequestsShouldMergeImpExtContextSearchAndSiteSearchAndCopyToRubiconImpExtRpTarget() - throws JsonProcessingException { - // given - final BidRequest bidRequest = givenBidRequest( - requestBuilder -> requestBuilder.site(Site.builder().search("site search").build()), - impBuilder -> impBuilder.video(Video.builder().build()), - identity()); - - final ObjectNode impExt = bidRequest.getImp().get(0).getExt(); - final ExtImpContext extImpContext = ExtImpContext.of(null); - extImpContext.addProperty("search", new TextNode("imp ext search")); - impExt.set("context", mapper.valueToTree(extImpContext)); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getExt) - .extracting(objectNode -> mapper.convertValue(objectNode, RubiconImpExt.class)) - .extracting(RubiconImpExt::getRp) - .extracting(RubiconImpExtRp::getTarget) - .containsOnly(mapper.readTree("{\"search\":[\"site search\", \"imp ext search\"]}")); - } - - @Test - public void makeHttpRequestsShouldMergeImpExtContextDataAndSiteAttributesAndCopyToRubiconImpExtRpTarget() { - // given - final BidRequest bidRequest = givenBidRequest( - requestBuilder -> requestBuilder.site(Site.builder() - .sectioncat(singletonList("site sectioncat")) - .pagecat(singletonList("site pagecat")) - .page("site page") - .ref("site ref") - .search("site search") - .build()), - impBuilder -> impBuilder.video(Video.builder().build()), - identity()); - - final ObjectNode impExtContextData = mapper.createObjectNode() - .set("sectioncat", mapper.createArrayNode().add("imp ext sectioncat")) - .set("pagecat", mapper.createArrayNode().add("imp ext pagecat")) - .put("page", "imp ext page") - .put("ref", "imp ext ref") - .put("search", "imp ext search"); - - final ObjectNode impExt = bidRequest.getImp().get(0).getExt(); - impExt.set("context", mapper.valueToTree(ExtImpContext.of(impExtContextData))); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getExt) - .extracting(objectNode -> mapper.convertValue(objectNode, RubiconImpExt.class)) - .extracting(RubiconImpExt::getRp) - .extracting(RubiconImpExtRp::getTarget) - .containsOnly(mapper.createObjectNode() - .set("sectioncat", mapper.createArrayNode() - .add("site sectioncat") - .add("imp ext sectioncat")) - .set("pagecat", mapper.createArrayNode() - .add("site pagecat") - .add("imp ext pagecat")) - .set("page", mapper.createArrayNode() - .add("site page") - .add("imp ext page")) - .set("ref", mapper.createArrayNode() - .add("site ref") - .add("imp ext ref")) - .set("search", mapper.createArrayNode() - .add("site search") - .add("imp ext search"))); - } - @Test public void makeHttpRequestsShouldOverridePbadslotIfPresentInRequestImpExt() { // given @@ -2829,73 +2715,6 @@ public void makeHttpRequestsShouldOverrideDfpAdunitCodeIfAdslotPresentInImpExtDa .containsExactly(TextNode.valueOf("adslotvalue")); } - @Test - public void makeHttpRequestsShouldOverrideDfpAdunitCodeIfAdslotPresentInImpExtContextDataAndAndAdserverNameIsGam() { - // given - final BidRequest bidRequest = givenBidRequest( - identity(), impBuilder -> impBuilder.video(Video.builder().build()), identity()); - - final ObjectNode dataNode = - mapper.createObjectNode() - .set("adserver", mapper.createObjectNode() - .put("adslot", "adslotvalue") - .put("name", "gam")); - - bidRequest.getImp().get(0).getExt() - .set("context", mapper.createObjectNode().set("data", dataNode)); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) - .extracting(HttpRequest::getPayload) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getExt) - .extracting(ext -> ext.at("/rp/target/dfp_ad_unit_code")) - .containsExactly(TextNode.valueOf("adslotvalue")); - } - - @Test - public void makeHttpRequestsShouldMergeImpExtContextDataAndAppAttributesAndCopyToRubiconImpExtRpTarget() { - // given - final BidRequest bidRequest = givenBidRequest( - requestBuilder -> requestBuilder.app(App.builder() - .sectioncat(singletonList("app sectioncat")) - .pagecat(singletonList("app pagecat")) - .build()), - impBuilder -> impBuilder.video(Video.builder().build()), - identity()); - - final ObjectNode impExtContextData = mapper.createObjectNode() - .set("sectioncat", mapper.createArrayNode().add("imp ext sectioncat")) - .set("pagecat", mapper.createArrayNode().add("imp ext pagecat")); - - final ObjectNode impExt = bidRequest.getImp().get(0).getExt(); - impExt.set("context", mapper.valueToTree(ExtImpContext.of(impExtContextData))); - - // when - final Result>> result = target.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()) - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getExt) - .extracting(objectNode -> mapper.convertValue(objectNode, RubiconImpExt.class)) - .extracting(RubiconImpExt::getRp) - .extracting(RubiconImpExtRp::getTarget) - .containsOnly(mapper.createObjectNode() - .set("sectioncat", mapper.createArrayNode() - .add("app sectioncat") - .add("imp ext sectioncat")) - .set("pagecat", mapper.createArrayNode() - .add("app pagecat") - .add("imp ext pagecat"))); - } - @Test public void makeHttpRequestsShouldCopySiteKeywords() { // given @@ -3964,6 +3783,16 @@ private static Data givenDataWithSegmentEntry(Integer segtax, String segmentId) .build(); } + private static Data givenTestDataWithSegmentEntries(Integer segtax) { + final List segments = IntStream.range(0, 1000) + .mapToObj(index -> Segment.builder().id("segmentId_" + index).build()) + .toList(); + return Data.builder() + .segment(segments) + .ext(mapper.createObjectNode().put("segtax", segtax)) + .build(); + } + private static PriceFloorRules givenFloors( UnaryOperator floorsCustomizer) { diff --git a/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-1.json b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-1.json new file mode 100644 index 00000000000..22cc0f89301 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-1.json @@ -0,0 +1,111 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1", + "secure": 1, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "ext": { + "rp": { + "mime": "text/html" + } + } + }, + "pmp": { + "deals": [ + { + "id": "dealId1", + "ext": { + "line": { + "lineitemid": "lineItem1", + "extlineitemid": "extLineItem1", + "sizes": [ + { + "w": 300, + "h": 250 + } + ] + } + } + }, + { + "id": "dealId3", + "ext": { + "line": { + "lineitemid": "lineItem3", + "extlineitemid": "extLineItem3", + "sizes": [ + { + "w": 300, + "h": 250 + } + ] + } + } + } + ] + }, + "ext": { + "rp": { + "zone_id": 4001, + "target": { + "line_item": "extLineItem1" + }, + "track": { + "mint": "", + "mint_version": "" + } + }, + "maxbids": 1 + } + } + ], + "source": { + "tid": "${json-unit.any-string}" + }, + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "ext": { + "rp": { + "account_id": 2001 + } + } + }, + "ext": { + "rp": { + "site_id": 3001 + }, + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "185.199.110.0", + "ext": { + "rp": {} + } + }, + "user": { + "ext": { + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + "fcapids": [ + "fcapId3" + ], + "rp": { + "target": { + "segtaxBLAH" : [ "3333", "6666", "2222", "5555" ] + } + } + } + }, + "at": 1, + "tmax": "${json-unit.any-number}" +} diff --git a/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-2.json b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-2.json new file mode 100644 index 00000000000..5c260149df2 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-2.json @@ -0,0 +1,96 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId2", + "secure": 1, + "banner": { + "format": [ + { + "w": 320, + "h": 320 + } + ], + "ext": { + "rp": { + "mime": "text/html" + } + } + }, + "pmp": { + "deals": [ + { + "id": "dealId2", + "ext": { + "line": { + "lineitemid": "lineItem2", + "extlineitemid": "extLineItem2", + "sizes": [ + { + "w": 320, + "h": 320 + } + ] + } + } + } + ] + }, + "ext": { + "rp": { + "zone_id": 4001, + "target": { + "line_item": "extLineItem2" + }, + "track": { + "mint": "", + "mint_version": "" + } + }, + "maxbids": 1 + } + } + ], + "source": { + "tid": "${json-unit.any-string}" + }, + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "ext": { + "rp": { + "account_id": 2001 + } + } + }, + "ext": { + "rp": { + "site_id": 3001 + }, + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "185.199.110.0", + "ext": { + "rp": {} + } + }, + "user": { + "ext": { + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + "fcapids": [ + "fcapId3" + ], + "rp": { + "target": { + "segtaxBLAH" : [ "3333", "6666", "2222", "5555" ] + } + } + } + }, + "at": 1, + "tmax": "${json-unit.any-number}" +} diff --git a/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-3.json b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-3.json new file mode 100644 index 00000000000..d1dd3a1fb59 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-3.json @@ -0,0 +1,111 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId1", + "secure": 1, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "ext": { + "rp": { + "mime": "text/html" + } + } + }, + "pmp": { + "deals": [ + { + "id": "dealId1", + "ext": { + "line": { + "lineitemid": "lineItem1", + "extlineitemid": "extLineItem1", + "sizes": [ + { + "w": 300, + "h": 250 + } + ] + } + } + }, + { + "id": "dealId3", + "ext": { + "line": { + "lineitemid": "lineItem3", + "extlineitemid": "extLineItem3", + "sizes": [ + { + "w": 300, + "h": 250 + } + ] + } + } + } + ] + }, + "ext": { + "rp": { + "zone_id": 4001, + "target": { + "line_item": "extLineItem3" + }, + "track": { + "mint": "", + "mint_version": "" + } + }, + "maxbids": 1 + } + } + ], + "source": { + "tid": "${json-unit.any-string}" + }, + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "ext": { + "rp": { + "account_id": 2001 + } + } + }, + "ext": { + "rp": { + "site_id": 3001 + }, + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "185.199.110.0", + "ext": { + "rp": {} + } + }, + "user": { + "ext": { + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + "fcapids": [ + "fcapId3" + ], + "rp": { + "target": { + "segtaxBLAH" : [ "3333", "6666", "2222", "5555" ] + } + } + } + }, + "at": 1, + "tmax": "${json-unit.any-number}" +} diff --git a/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-4.json b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-4.json new file mode 100644 index 00000000000..8f39e073931 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-4.json @@ -0,0 +1,96 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId4", + "secure": 1, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "ext": { + "rp": { + "mime": "text/html" + } + } + }, + "pmp": { + "deals": [ + { + "id": "dealId3", + "ext": { + "line": { + "lineitemid": "lineItem3", + "extlineitemid": "extLineItem3", + "sizes": [ + { + "w": 300, + "h": 250 + } + ] + } + } + } + ] + }, + "ext": { + "rp": { + "zone_id": 4001, + "target": { + "line_item": "extLineItem3" + }, + "track": { + "mint": "", + "mint_version": "" + } + }, + "maxbids": 1 + } + } + ], + "source": { + "tid": "${json-unit.any-string}" + }, + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "ext": { + "rp": { + "account_id": 2001 + } + } + }, + "ext": { + "rp": { + "site_id": 3001 + }, + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "185.199.110.0", + "ext": { + "rp": {} + } + }, + "user": { + "ext": { + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + "fcapids": [ + "fcapId3" + ], + "rp": { + "target": { + "segtaxBLAH" : [ "3333", "6666", "2222", "5555" ] + } + } + } + }, + "at": 1, + "tmax": "${json-unit.any-number}" +} diff --git a/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-5.json b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-5.json new file mode 100644 index 00000000000..402dc7da0ad --- /dev/null +++ b/src/test/resources/org/prebid/server/it/deals/test-rubicon-bid-request-5.json @@ -0,0 +1,110 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId4", + "secure": 1, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "ext": { + "rp": { + "mime": "text/html" + } + } + }, + "pmp": { + "deals": [ + { + "id": "dealId1", + "ext": { + "line": { + "lineitemid": "lineItem1", + "extlineitemid": "extLineItem1", + "sizes": [ + { + "w": 300, + "h": 250 + } + ] + } + } + }, + { + "id": "dealId3", + "ext": { + "line": { + "lineitemid": "lineItem3", + "extlineitemid": "extLineItem3", + "sizes": [ + { + "w": 300, + "h": 250 + } + ] + } + } + } + ] + }, + "ext": { + "rp": { + "zone_id": 4001, + "target": { + "line_item": "extLineItem3" + }, + "track": { + "mint": "", + "mint_version": "" + } + } + } + } + ], + "source": { + "tid": "${json-unit.any-string}" + }, + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "ext": { + "rp": { + "account_id": 2001 + } + } + }, + "ext": { + "rp": { + "site_id": 3001 + }, + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "185.199.110.0", + "ext": { + "rp": {} + } + }, + "user": { + "ext": { + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + "fcapids": [ + "fcapId3" + ], + "rp": { + "target": { + "segtaxBLAH" : [ "3333", "6666", "2222", "5555" ] + } + } + } + }, + "at": 1, + "tmax": "${json-unit.any-number}" +} diff --git a/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-request-1.json b/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-request-1.json index 5637a0f0026..e53c80ad46a 100644 --- a/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/hooks/reject/test-rubicon-bid-request-1.json @@ -24,11 +24,6 @@ "ext": { "rp": { "zone_id": 4001, - "target": { - "page": [ - "http://www.example.com" - ] - }, "track": { "mint": "", "mint_version": "" diff --git a/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-request-1.json b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-request-1.json index 89d2ac57bcb..3af3db2ec3a 100644 --- a/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/hooks/sample-module/test-rubicon-bid-request-1.json @@ -25,11 +25,6 @@ "ext": { "rp": { "zone_id": 4001, - "target": { - "page": [ - "http://www.example.com" - ] - }, "track": { "mint": "", "mint_version": "" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/magnite/test-magnite-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/magnite/test-magnite-bid-request.json index 15584c3d343..541f4302b67 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/magnite/test-magnite-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/magnite/test-magnite-bid-request.json @@ -14,11 +14,6 @@ "ext": { "rp": { "zone_id": 4001, - "target": { - "page": [ - "http://www.example.com" - ] - }, "track": { "mint": "", "mint_version": "" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-rubicon-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-rubicon-bid-request.json index 15584c3d343..541f4302b67 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-rubicon-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-rubicon-bid-request.json @@ -14,11 +14,6 @@ "ext": { "rp": { "zone_id": 4001, - "target": { - "page": [ - "http://www.example.com" - ] - }, "track": { "mint": "", "mint_version": ""