From d80b6cd56c00321a24d6d103d16cc08f3ce311dd Mon Sep 17 00:00:00 2001 From: Maksym Danylov Date: Thu, 21 May 2026 12:04:16 +0300 Subject: [PATCH 1/2] Prebid Mobile: makes creative size transformation based on pxRatio. --- .../server/auction/InterstitialProcessor.java | 30 ++++- .../ext/request/ExtRequestPrebidSdk.java | 17 ++- .../auction/InterstitialProcessorTest.java | 124 ++++++++++++++++++ 3 files changed, 168 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/InterstitialProcessor.java b/src/main/java/org/prebid/server/auction/InterstitialProcessor.java index 7aa83960199..0384be9b8b9 100644 --- a/src/main/java/org/prebid/server/auction/InterstitialProcessor.java +++ b/src/main/java/org/prebid/server/auction/InterstitialProcessor.java @@ -10,7 +10,11 @@ import org.prebid.server.proto.openrtb.ext.request.ExtDevice; import org.prebid.server.proto.openrtb.ext.request.ExtDeviceInt; import org.prebid.server.proto.openrtb.ext.request.ExtDevicePrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSdk; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -36,15 +40,17 @@ private BidRequest processBidRequest(BidRequest bidRequest) { if (extDeviceInt != null) { final int minWidthPerc = extDeviceInt.getMinWidthPerc(); final int minHeightPerc = extDeviceInt.getMinHeightPerc(); + final boolean usePxRatio = usePxRatio(bidRequest); final List updatedImps = bidRequest.getImp().stream() - .map(imp -> processInterstitialImp(imp, device, minWidthPerc, minHeightPerc)) + .map(imp -> processInterstitialImp(imp, device, minWidthPerc, minHeightPerc, usePxRatio)) .toList(); bidRequest = bidRequest.toBuilder().imp(updatedImps).build(); } return bidRequest; } - private Imp processInterstitialImp(Imp imp, Device device, int minWidthPerc, int minHeightPerc) { + private Imp processInterstitialImp(Imp imp, Device device, int minWidthPerc, int minHeightPerc, + boolean usePxRatio) { if (!isInterstitial(imp)) { return imp; } @@ -62,6 +68,11 @@ private Imp processInterstitialImp(Imp imp, Device device, int minWidthPerc, int if (maxHeight == null || maxWidth == null || (maxHeight == 1 && maxWidth == 1)) { maxHeight = device.getH(); maxWidth = device.getW(); + if (usePxRatio) { + final BigDecimal pxratio = device.getPxratio(); + maxHeight = deviceSizeToDips(maxHeight, pxratio); + maxWidth = deviceSizeToDips(maxWidth, pxratio); + } } if (maxHeight == null || maxWidth == null) { @@ -92,6 +103,21 @@ private ExtDeviceInt getExtDeviceInt(Device device) { return extDevicePrebid != null ? extDevicePrebid.getInterstitial() : null; } + private static boolean usePxRatio(BidRequest bidRequest) { + final ExtRequest extRequest = bidRequest.getExt(); + final ExtRequestPrebid prebid = extRequest != null ? extRequest.getPrebid() : null; + final ExtRequestPrebidSdk sdk = prebid != null ? prebid.getSdk() : null; + return sdk != null && Objects.equals(sdk.getUsePxRatio(), true); + } + + private static Integer deviceSizeToDips(Integer size, BigDecimal pxratio) { + if (size == null || pxratio == null || pxratio.signum() <= 0) { + return size; + } + + return Math.max(1, (int) Math.round(size / pxratio.doubleValue())); + } + private static class InterstitialSize { private static final List INTERSTITIAL_SIZES = new ArrayList<>(); diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdk.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdk.java index fe6ae9d55f8..396af74fdef 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdk.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdk.java @@ -1,5 +1,6 @@ package org.prebid.server.proto.openrtb.ext.request; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Value; import java.util.List; @@ -7,11 +8,25 @@ /** * Defines the contract for bidrequest.ext.prebid.sdk */ -@Value(staticConstructor = "of") +@Value public class ExtRequestPrebidSdk { /** * Defines the contract for bidrequest.ext.prebid.sdk.renderers */ List renderers; + + /** + * Defines the contract for bidrequest.ext.prebid.sdk.usepxratio + */ + @JsonProperty("usepxratio") + Boolean usePxRatio; + + public static ExtRequestPrebidSdk of(List renderers) { + return new ExtRequestPrebidSdk(renderers, null); + } + + public static ExtRequestPrebidSdk of(List renderers, Boolean usePxRatio) { + return new ExtRequestPrebidSdk(renderers, usePxRatio); + } } diff --git a/src/test/java/org/prebid/server/auction/InterstitialProcessorTest.java b/src/test/java/org/prebid/server/auction/InterstitialProcessorTest.java index 662c58e7aa8..a6d3908cfb1 100644 --- a/src/test/java/org/prebid/server/auction/InterstitialProcessorTest.java +++ b/src/test/java/org/prebid/server/auction/InterstitialProcessorTest.java @@ -11,6 +11,11 @@ import org.prebid.server.proto.openrtb.ext.request.ExtDevice; import org.prebid.server.proto.openrtb.ext.request.ExtDeviceInt; import org.prebid.server.proto.openrtb.ext.request.ExtDevicePrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSdk; + +import java.math.BigDecimal; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; @@ -71,6 +76,28 @@ public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingSize Format.builder().w(320).h(481).build()); } + @Test + public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingDeviceSizeInDipsWhenFormatIsEmpty() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().build()).instl(1).build())) + .device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3)) + .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(60, 60)))) + .build()) + .ext(usePxRatioExt()) + .build(); + + // when + final BidRequest result = interstitialProcessor.process(bidRequest); + + // then + assertThat(result.getImp()) + .extracting(Imp::getBanner) + .flatExtracting(Banner::getFormat) + .contains(Format.builder().w(320).h(480).build()) + .doesNotContain(Format.builder().w(768).h(1024).build()); + } + @Test public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingSizesFromDeviceWhenFormatIsOneToOne() { // given @@ -96,6 +123,97 @@ public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingSize Format.builder().w(320).h(481).build()); } + @Test + public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingDeviceSizeInDipsWhenFormatIsOneToOne() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().format(singletonList( + Format.builder().w(1).h(1).build())).build()).instl(1).build())) + .device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3)) + .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(60, 60)))) + .build()) + .ext(usePxRatioExt()) + .build(); + + // when + final BidRequest result = interstitialProcessor.process(bidRequest); + + // then + assertThat(result.getImp()) + .extracting(Imp::getBanner) + .flatExtracting(Banner::getFormat) + .contains(Format.builder().w(320).h(480).build()) + .doesNotContain(Format.builder().w(768).h(1024).build()); + } + + @Test + public void processShouldNotConvertExplicitFormatSizeUsingDevicePxratio() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder() + .format(singletonList(Format.builder().w(400).h(600).build())).build()).instl(1) + .build())) + .device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3)) + .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(80, 80)))) + .build()) + .ext(usePxRatioExt()) + .build(); + + // when + final BidRequest result = interstitialProcessor.process(bidRequest); + + // then + assertThat(result.getImp()) + .extracting(Imp::getBanner) + .flatExtracting(Banner::getFormat) + .containsOnly(Format.builder().w(320).h(480).build(), + Format.builder().w(336).h(544).build(), + Format.builder().w(320).h(568).build(), + Format.builder().w(320).h(500).build(), + Format.builder().w(320).h(481).build()); + } + + @Test + public void processShouldKeepCurrentDeviceSizeBehaviorWhenUsePxRatioIsTrueAndDevicePxRatioIsAbsent() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().build()).instl(1).build())) + .device(Device.builder().w(1080).h(1920) + .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(1, 1)))) + .build()) + .ext(usePxRatioExt()) + .build(); + + // when + final BidRequest result = interstitialProcessor.process(bidRequest); + + // then + assertThat(result.getImp()) + .extracting(Imp::getBanner) + .flatExtracting(Banner::getFormat) + .contains(Format.builder().w(768).h(1024).build()); + } + + @Test + public void processShouldKeepCurrentDeviceSizeBehaviorWhenUsePxRatioIsAbsent() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().build()).instl(1).build())) + .device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3)) + .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(1, 1)))) + .build()) + .build(); + + // when + final BidRequest result = interstitialProcessor.process(bidRequest); + + // then + assertThat(result.getImp()) + .extracting(Imp::getBanner) + .flatExtracting(Banner::getFormat) + .contains(Format.builder().w(768).h(1024).build()); + } + @Test public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsLimitedByTen() { // given @@ -266,4 +384,10 @@ public void processShouldNotUpdateImpWhenInterstitialSizesWereNotFound() { .build()) .build()); } + + private static ExtRequest usePxRatioExt() { + return ExtRequest.of(ExtRequestPrebid.builder() + .sdk(ExtRequestPrebidSdk.of(null, true)) + .build()); + } } From bf84e631e12b96b878d97f69118f2bed028485a8 Mon Sep 17 00:00:00 2001 From: Maksym Danylov Date: Sun, 5 Jul 2026 00:48:09 +0300 Subject: [PATCH 2/2] Resolves PR issues --- .../server/auction/InterstitialProcessor.java | 127 +++++++++--------- .../ext/request/ExtRequestPrebidSdk.java | 4 - .../auction/InterstitialProcessorTest.java | 105 ++++++++++++--- .../bidder/nativo/NativoBidderTest.java | 2 +- 4 files changed, 155 insertions(+), 83 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/InterstitialProcessor.java b/src/main/java/org/prebid/server/auction/InterstitialProcessor.java index 0384be9b8b9..0ae5b3cd6fd 100644 --- a/src/main/java/org/prebid/server/auction/InterstitialProcessor.java +++ b/src/main/java/org/prebid/server/auction/InterstitialProcessor.java @@ -5,7 +5,9 @@ import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; +import lombok.Value; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.BooleanUtils; import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.proto.openrtb.ext.request.ExtDevice; import org.prebid.server.proto.openrtb.ext.request.ExtDeviceInt; @@ -18,6 +20,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Stream; public class InterstitialProcessor { @@ -49,8 +52,19 @@ private BidRequest processBidRequest(BidRequest bidRequest) { return bidRequest; } - private Imp processInterstitialImp(Imp imp, Device device, int minWidthPerc, int minHeightPerc, + private static boolean usePxRatio(BidRequest bidRequest) { + final ExtRequest extRequest = bidRequest.getExt(); + final ExtRequestPrebid prebid = extRequest != null ? extRequest.getPrebid() : null; + final ExtRequestPrebidSdk sdk = prebid != null ? prebid.getSdk() : null; + return sdk != null && BooleanUtils.isTrue(sdk.getUsePxRatio()); + } + + private Imp processInterstitialImp(Imp imp, + Device device, + int minWidthPerc, + int minHeightPerc, boolean usePxRatio) { + if (!isInterstitial(imp)) { return imp; } @@ -60,41 +74,58 @@ private Imp processInterstitialImp(Imp imp, Device device, int minWidthPerc, int return imp; } + final InterstitialSize maxSize = getMaxSize(banner, device, imp.getId(), usePxRatio); + final double minWidth = getMinSize(maxSize.getW(), minWidthPerc); + final double minHeight = getMinSize(maxSize.getH(), minHeightPerc); + + final List interstitialFormats = InterstitialSize.getNestedSizes(minWidth, minHeight, maxSize) + .map(size -> Format.builder().w(size.w).h(size.h).build()) + .toList(); + + return CollectionUtils.isNotEmpty(interstitialFormats) + ? imp.toBuilder().banner(banner.toBuilder().format(interstitialFormats).build()).build() + : imp; + } + + private static InterstitialSize getMaxSize(Banner banner, Device device, String impId, boolean usePxRatio) { final List formats = banner.getFormat(); final Format firstFormat = CollectionUtils.isEmpty(formats) ? null : formats.getFirst(); - Integer maxHeight = firstFormat != null ? firstFormat.getH() : null; - Integer maxWidth = firstFormat != null ? firstFormat.getW() : null; + final Integer firstFormatWidth = firstFormat != null ? firstFormat.getW() : null; + final Integer firstFormatHeight = firstFormat != null ? firstFormat.getH() : null; - if (maxHeight == null || maxWidth == null || (maxHeight == 1 && maxWidth == 1)) { - maxHeight = device.getH(); - maxWidth = device.getW(); - if (usePxRatio) { - final BigDecimal pxratio = device.getPxratio(); - maxHeight = deviceSizeToDips(maxHeight, pxratio); - maxWidth = deviceSizeToDips(maxWidth, pxratio); - } + if (firstFormatWidth != null + && firstFormatHeight != null + && (firstFormatWidth != 1 || firstFormatHeight != 1)) { + + return InterstitialSize.interstitialSize(firstFormatWidth, firstFormatHeight); } - if (maxHeight == null || maxWidth == null) { + final Integer deviceWidth = device.getW(); + final Integer deviceHeight = device.getH(); + if (deviceWidth == null || deviceHeight == null) { throw new InvalidRequestException( "Unable to read max interstitial size for Imp id=%s (No Device sizes and no Format objects)" - .formatted(imp.getId())); + .formatted(impId)); } - final double minHeight = (double) maxHeight / 100 * minHeightPerc; - final double minWidth = (double) maxWidth / 100 * minWidthPerc; + if (usePxRatio) { + final BigDecimal pxRatio = device.getPxratio(); + return InterstitialSize.interstitialSize( + deviceSizeToDips(deviceWidth, pxRatio), + deviceSizeToDips(deviceHeight, pxRatio)); + } - final List interstitialFormats = - InterstitialSize.getNestedSizes(minWidth, minHeight, maxWidth, maxHeight, MAX_SIZES_COUNT) - .stream() - .map(interstitialSize -> Format.builder().w(interstitialSize.w).h(interstitialSize.h).build()) - .toList(); + return InterstitialSize.interstitialSize(deviceWidth, deviceHeight); + } - if (CollectionUtils.isEmpty(interstitialFormats)) { - return imp; - } + private static int deviceSizeToDips(int size, BigDecimal pxRatio) { + return pxRatio != null && pxRatio.signum() > 0 + ? Math.max(1, (int) Math.round(size / pxRatio.doubleValue())) + : size; + } - return imp.toBuilder().banner(banner.toBuilder().format(interstitialFormats).build()).build(); + private static double getMinSize(int maxSize, int minSizePerc) { + return maxSize / 100.0 * minSizePerc; } private ExtDeviceInt getExtDeviceInt(Device device) { @@ -103,21 +134,7 @@ private ExtDeviceInt getExtDeviceInt(Device device) { return extDevicePrebid != null ? extDevicePrebid.getInterstitial() : null; } - private static boolean usePxRatio(BidRequest bidRequest) { - final ExtRequest extRequest = bidRequest.getExt(); - final ExtRequestPrebid prebid = extRequest != null ? extRequest.getPrebid() : null; - final ExtRequestPrebidSdk sdk = prebid != null ? prebid.getSdk() : null; - return sdk != null && Objects.equals(sdk.getUsePxRatio(), true); - } - - private static Integer deviceSizeToDips(Integer size, BigDecimal pxratio) { - if (size == null || pxratio == null || pxratio.signum() <= 0) { - return size; - } - - return Math.max(1, (int) Math.round(size / pxratio.doubleValue())); - } - + @Value(staticConstructor = "interstitialSize") private static class InterstitialSize { private static final List INTERSTITIAL_SIZES = new ArrayList<>(); @@ -375,33 +392,19 @@ private static class InterstitialSize { INTERSTITIAL_SIZES.add(interstitialSize(120, 20)); } - private final Integer w; - private final Integer h; - - private InterstitialSize(Integer w, Integer h) { - this.w = w; - this.h = h; - } - - private static InterstitialSize interstitialSize(Integer w, Integer h) { - return new InterstitialSize(w, h); - } - - private static List getNestedSizes(double minWidth, - double minHeight, - double maxWidth, - double maxHeight, - int count) { + int w; + int h; + private static Stream getNestedSizes(double minWidth, double minHeight, + InterstitialSize max) { return INTERSTITIAL_SIZES.stream() - .filter(size -> isNested(size, minWidth, minHeight, maxWidth, maxHeight)) - .limit(count) - .toList(); + .filter(size -> isNested(size, minWidth, minHeight, max)) + .limit(MAX_SIZES_COUNT); } - private static boolean isNested(InterstitialSize size, double minWidth, double minHeight, double maxWidth, - double maxHeight) { - return size.w >= minWidth && size.w <= maxWidth && size.h >= minHeight && size.h <= maxHeight; + private static boolean isNested(InterstitialSize size, double minWidth, double minHeight, + InterstitialSize max) { + return size.w >= minWidth && size.w <= max.w && size.h >= minHeight && size.h <= max.h; } } } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdk.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdk.java index 396af74fdef..cff39b5a778 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdk.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebidSdk.java @@ -22,10 +22,6 @@ public class ExtRequestPrebidSdk { @JsonProperty("usepxratio") Boolean usePxRatio; - public static ExtRequestPrebidSdk of(List renderers) { - return new ExtRequestPrebidSdk(renderers, null); - } - public static ExtRequestPrebidSdk of(List renderers, Boolean usePxRatio) { return new ExtRequestPrebidSdk(renderers, usePxRatio); } diff --git a/src/test/java/org/prebid/server/auction/InterstitialProcessorTest.java b/src/test/java/org/prebid/server/auction/InterstitialProcessorTest.java index a6d3908cfb1..123bfcedb3b 100644 --- a/src/test/java/org/prebid/server/auction/InterstitialProcessorTest.java +++ b/src/test/java/org/prebid/server/auction/InterstitialProcessorTest.java @@ -45,7 +45,7 @@ public void processShouldReturnBidRequestUpdatedWithImpsInterstitialFormat() { assertThat(result.getImp()) .extracting(Imp::getBanner) .flatExtracting(Banner::getFormat) - .containsOnly(Format.builder().w(320).h(480).build(), + .containsExactly(Format.builder().w(320).h(480).build(), Format.builder().w(336).h(544).build(), Format.builder().w(320).h(568).build(), Format.builder().w(320).h(500).build(), @@ -69,7 +69,7 @@ public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingSize assertThat(result.getImp()) .extracting(Imp::getBanner) .flatExtracting(Banner::getFormat) - .containsOnly(Format.builder().w(320).h(480).build(), + .containsExactly(Format.builder().w(320).h(480).build(), Format.builder().w(336).h(544).build(), Format.builder().w(320).h(568).build(), Format.builder().w(320).h(500).build(), @@ -81,7 +81,10 @@ public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingDevi // given final BidRequest bidRequest = BidRequest.builder() .imp(singletonList(Imp.builder().banner(Banner.builder().build()).instl(1).build())) - .device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3)) + .device(Device.builder() + .w(1080) + .h(1920) + .pxratio(BigDecimal.valueOf(3)) .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(60, 60)))) .build()) .ext(usePxRatioExt()) @@ -94,8 +97,16 @@ public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingDevi assertThat(result.getImp()) .extracting(Imp::getBanner) .flatExtracting(Banner::getFormat) - .contains(Format.builder().w(320).h(480).build()) - .doesNotContain(Format.builder().w(768).h(1024).build()); + .containsExactly(Format.builder().w(300).h(600).build(), + Format.builder().w(320).h(480).build(), + Format.builder().w(250).h(600).build(), + Format.builder().w(360).h(640).build(), + Format.builder().w(320).h(640).build(), + Format.builder().w(300).h(480).build(), + Format.builder().w(336).h(544).build(), + Format.builder().w(303).h(603).build(), + Format.builder().w(320).h(568).build(), + Format.builder().w(301).h(601).build()); } @Test @@ -116,7 +127,7 @@ public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingSize assertThat(result.getImp()) .extracting(Imp::getBanner) .flatExtracting(Banner::getFormat) - .containsOnly(Format.builder().w(320).h(480).build(), + .containsExactly(Format.builder().w(320).h(480).build(), Format.builder().w(336).h(544).build(), Format.builder().w(320).h(568).build(), Format.builder().w(320).h(500).build(), @@ -129,7 +140,10 @@ public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingDevi final BidRequest bidRequest = BidRequest.builder() .imp(singletonList(Imp.builder().banner(Banner.builder().format(singletonList( Format.builder().w(1).h(1).build())).build()).instl(1).build())) - .device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3)) + .device(Device.builder() + .w(1080) + .h(1920) + .pxratio(BigDecimal.valueOf(3)) .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(60, 60)))) .build()) .ext(usePxRatioExt()) @@ -142,8 +156,16 @@ public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingDevi assertThat(result.getImp()) .extracting(Imp::getBanner) .flatExtracting(Banner::getFormat) - .contains(Format.builder().w(320).h(480).build()) - .doesNotContain(Format.builder().w(768).h(1024).build()); + .containsExactly(Format.builder().w(300).h(600).build(), + Format.builder().w(320).h(480).build(), + Format.builder().w(250).h(600).build(), + Format.builder().w(360).h(640).build(), + Format.builder().w(320).h(640).build(), + Format.builder().w(300).h(480).build(), + Format.builder().w(336).h(544).build(), + Format.builder().w(303).h(603).build(), + Format.builder().w(320).h(568).build(), + Format.builder().w(301).h(601).build()); } @Test @@ -153,7 +175,10 @@ public void processShouldNotConvertExplicitFormatSizeUsingDevicePxratio() { .imp(singletonList(Imp.builder().banner(Banner.builder() .format(singletonList(Format.builder().w(400).h(600).build())).build()).instl(1) .build())) - .device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3)) + .device(Device.builder() + .w(1080) + .h(1920) + .pxratio(BigDecimal.valueOf(3)) .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(80, 80)))) .build()) .ext(usePxRatioExt()) @@ -166,7 +191,7 @@ public void processShouldNotConvertExplicitFormatSizeUsingDevicePxratio() { assertThat(result.getImp()) .extracting(Imp::getBanner) .flatExtracting(Banner::getFormat) - .containsOnly(Format.builder().w(320).h(480).build(), + .containsExactly(Format.builder().w(320).h(480).build(), Format.builder().w(336).h(544).build(), Format.builder().w(320).h(568).build(), Format.builder().w(320).h(500).build(), @@ -178,7 +203,9 @@ public void processShouldKeepCurrentDeviceSizeBehaviorWhenUsePxRatioIsTrueAndDev // given final BidRequest bidRequest = BidRequest.builder() .imp(singletonList(Imp.builder().banner(Banner.builder().build()).instl(1).build())) - .device(Device.builder().w(1080).h(1920) + .device(Device.builder() + .w(1080) + .h(1920) .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(1, 1)))) .build()) .ext(usePxRatioExt()) @@ -191,7 +218,16 @@ public void processShouldKeepCurrentDeviceSizeBehaviorWhenUsePxRatioIsTrueAndDev assertThat(result.getImp()) .extracting(Imp::getBanner) .flatExtracting(Banner::getFormat) - .contains(Format.builder().w(768).h(1024).build()); + .containsExactly(Format.builder().w(300).h(250).build(), + Format.builder().w(728).h(90).build(), + Format.builder().w(160).h(600).build(), + Format.builder().w(320).h(50).build(), + Format.builder().w(300).h(600).build(), + Format.builder().w(970).h(250).build(), + Format.builder().w(970).h(1000).build(), + Format.builder().w(320).h(320).build(), + Format.builder().w(768).h(1024).build(), + Format.builder().w(1024).h(768).build()); } @Test @@ -199,7 +235,10 @@ public void processShouldKeepCurrentDeviceSizeBehaviorWhenUsePxRatioIsAbsent() { // given final BidRequest bidRequest = BidRequest.builder() .imp(singletonList(Imp.builder().banner(Banner.builder().build()).instl(1).build())) - .device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3)) + .device(Device.builder() + .w(1080) + .h(1920) + .pxratio(BigDecimal.valueOf(3)) .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(1, 1)))) .build()) .build(); @@ -211,7 +250,41 @@ public void processShouldKeepCurrentDeviceSizeBehaviorWhenUsePxRatioIsAbsent() { assertThat(result.getImp()) .extracting(Imp::getBanner) .flatExtracting(Banner::getFormat) - .contains(Format.builder().w(768).h(1024).build()); + .containsExactly(Format.builder().w(300).h(250).build(), + Format.builder().w(728).h(90).build(), + Format.builder().w(160).h(600).build(), + Format.builder().w(320).h(50).build(), + Format.builder().w(300).h(600).build(), + Format.builder().w(970).h(250).build(), + Format.builder().w(970).h(1000).build(), + Format.builder().w(320).h(320).build(), + Format.builder().w(768).h(1024).build(), + Format.builder().w(1024).h(768).build()); + } + + @Test + public void processShouldNotTruncateMinimumInterstitialSizeThreshold() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder() + .format(singletonList(Format.builder().w(301).h(500).build())).build()).instl(1) + .build())) + .device(Device.builder() + .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(80, 80)))) + .build()) + .build(); + + // when + final BidRequest result = interstitialProcessor.process(bidRequest); + + // then + assertThat(result.getImp()) + .extracting(Imp::getBanner) + .flatExtracting(Banner::getFormat) + .containsExactly(Format.builder().w(300).h(480).build(), + Format.builder().w(300).h(500).build(), + Format.builder().w(300).h(431).build(), + Format.builder().w(300).h(430).build()); } @Test @@ -233,7 +306,7 @@ public void processShouldReturnBidRequestUpdatedWithInterstitialFormatsLimitedBy assertThat(result.getImp()) .extracting(Imp::getBanner) .flatExtracting(Banner::getFormat) - .containsOnly(Format.builder().w(300).h(250).build(), + .containsExactly(Format.builder().w(300).h(250).build(), Format.builder().w(160).h(600).build(), Format.builder().w(320).h(50).build(), Format.builder().w(300).h(600).build(), diff --git a/src/test/java/org/prebid/server/bidder/nativo/NativoBidderTest.java b/src/test/java/org/prebid/server/bidder/nativo/NativoBidderTest.java index f9bd907ef85..a99552283f0 100644 --- a/src/test/java/org/prebid/server/bidder/nativo/NativoBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/nativo/NativoBidderTest.java @@ -276,7 +276,7 @@ private static BidRequest givenBidRequestWithRenderer(UnaryOperator